diff --git a/swh/web/browse/views/release.py b/swh/web/browse/views/release.py index cadbd171..3f9f80d8 100644 --- a/swh/web/browse/views/release.py +++ b/swh/web/browse/views/release.py @@ -1,237 +1,235 @@ # Copyright (C) 2017-2020 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information from django.shortcuts import render import sentry_sdk +from swh.model.identifiers import CONTENT, DIRECTORY, RELEASE, REVISION, SNAPSHOT from swh.web.browse.browseurls import browse_route from swh.web.browse.snapshot_context import get_snapshot_context from swh.web.browse.utils import ( gen_revision_link, gen_link, gen_snapshot_link, get_swh_persistent_ids, gen_directory_link, gen_content_link, gen_release_link, gen_person_mail_link, ) from swh.web.common import service from swh.web.common.exc import NotFoundExc, handle_view_exception +from swh.web.common.typing import ReleaseMetadata from swh.web.common.utils import reverse, format_utc_iso_date @browse_route( r"release/(?P[0-9a-f]+)/", view_name="browse-release", checksum_args=["sha1_git"], ) def release_browse(request, sha1_git): """ Django view that produces an HTML display of a release identified by its id. The url that points to it is :http:get:`/browse/release/(sha1_git)/`. """ try: release = service.lookup_release(sha1_git) - snapshot_context = None + snapshot_context = {} origin_info = None snapshot_id = request.GET.get("snapshot_id", None) origin_url = request.GET.get("origin_url", None) if not origin_url: origin_url = request.GET.get("origin", None) timestamp = request.GET.get("timestamp", None) visit_id = request.GET.get("visit_id", None) if origin_url: try: snapshot_context = get_snapshot_context( snapshot_id, origin_url, timestamp, visit_id ) except NotFoundExc: raw_rel_url = reverse("browse-release", url_args={"sha1_git": sha1_git}) error_message = ( "The Software Heritage archive has a release " "with the hash you provided but the origin " "mentioned in your request appears broken: %s. " "Please check the URL and try again.\n\n" "Nevertheless, you can still browse the release " "without origin information: %s" % (gen_link(origin_url), gen_link(raw_rel_url)) ) raise NotFoundExc(error_message) origin_info = snapshot_context["origin_info"] elif snapshot_id: snapshot_context = get_snapshot_context(snapshot_id) except Exception as exc: return handle_view_exception(request, exc) - release_data = {} - - release_data["author"] = "None" - if release["author"]: - release_data["author"] = gen_person_mail_link(release["author"]) - release_data["date"] = format_utc_iso_date(release["date"]) - release_data["release"] = sha1_git - release_data["name"] = release["name"] - release_data["synthetic"] = release["synthetic"] - release_data["target"] = release["target"] - release_data["target type"] = release["target_type"] - + target_url = None + if release["target_type"] == REVISION: + target_url = gen_revision_link(release["target"]) + elif release["target_type"] == CONTENT: + target_url = gen_content_link(release["target"]) + elif release["target_type"] == DIRECTORY: + target_url = gen_directory_link(release["target"]) + elif release["target_type"] == RELEASE: + target_url = gen_release_link(release["target"]) + + snapshot_id = None + browse_snp_link = None if snapshot_context: - if release["target_type"] == "revision": - release_data["context-independent target"] = gen_revision_link( - release["target"] - ) - elif release["target_type"] == "content": - release_data["context-independent target"] = gen_content_link( - release["target"] - ) - elif release["target_type"] == "directory": - release_data["context-independent target"] = gen_directory_link( - release["target"] - ) - elif release["target_type"] == "release": - release_data["context-independent target"] = gen_release_link( - release["target"] - ) + snapshot_id = snapshot_context["snapshot_id"] + browse_snp_link = gen_snapshot_link(snapshot_id) + + release_metadata = ReleaseMetadata( + object_type=RELEASE, + release=sha1_git, + release_url=gen_release_link(release["id"]), + author=release["author"]["fullname"] if release["author"] else "None", + author_url=gen_person_mail_link(release["author"]) + if release["author"] + else "None", + date=format_utc_iso_date(release["date"]), + name=release["name"], + synthetic=release["synthetic"], + target=release["target"], + target_type=release["target_type"], + target_url=target_url, + snapshot=snapshot_context.get("snapshot_id", None), + snapshot_url=browse_snp_link, + origin_url=origin_url, + ) release_note_lines = [] if release["message"]: release_note_lines = release["message"].split("\n") vault_cooking = None rev_directory = None target_link = None - if release["target_type"] == "revision": + if release["target_type"] == REVISION: target_link = gen_revision_link( release["target"], snapshot_context=snapshot_context, link_text=None, link_attrs=None, ) try: revision = service.lookup_revision(release["target"]) rev_directory = revision["directory"] vault_cooking = { "directory_context": True, "directory_id": rev_directory, "revision_context": True, "revision_id": release["target"], } except Exception as exc: sentry_sdk.capture_exception(exc) - elif release["target_type"] == "directory": + elif release["target_type"] == DIRECTORY: target_link = gen_directory_link( release["target"], snapshot_context=snapshot_context, link_text=None, link_attrs=None, ) try: # check directory exists service.lookup_directory(release["target"]) vault_cooking = { "directory_context": True, "directory_id": release["target"], "revision_context": False, "revision_id": None, } except Exception as exc: sentry_sdk.capture_exception(exc) - elif release["target_type"] == "content": + elif release["target_type"] == CONTENT: target_link = gen_content_link( release["target"], snapshot_context=snapshot_context, link_text=None, link_attrs=None, ) - elif release["target_type"] == "release": + elif release["target_type"] == RELEASE: target_link = gen_release_link( release["target"], snapshot_context=snapshot_context, link_text=None, link_attrs=None, ) rev_directory_url = None if rev_directory is not None: if origin_info: rev_directory_url = reverse( "browse-origin-directory", query_params={ "origin_url": origin_info["url"], "release": release["name"], }, ) elif snapshot_id: rev_directory_url = reverse( "browse-snapshot-directory", url_args={"snapshot_id": snapshot_id}, query_params={"release": release["name"]}, ) else: rev_directory_url = reverse( "browse-directory", url_args={"sha1_git": rev_directory} ) directory_link = None if rev_directory_url is not None: directory_link = gen_link(rev_directory_url, rev_directory) release["directory_link"] = directory_link release["target_link"] = target_link - if snapshot_context: - release_data["snapshot"] = snapshot_context["snapshot_id"] - - if origin_info: - release_data["context-independent release"] = gen_release_link(release["id"]) - release_data["origin url"] = gen_link(origin_info["url"], origin_info["url"]) - browse_snapshot_link = gen_snapshot_link(snapshot_context["snapshot_id"]) - release_data["context-independent snapshot"] = browse_snapshot_link - - swh_objects = [{"type": "release", "id": sha1_git}] + swh_objects = [{"type": RELEASE, "id": sha1_git}] if snapshot_context: snapshot_id = snapshot_context["snapshot_id"] if snapshot_id: - swh_objects.append({"type": "snapshot", "id": snapshot_id}) + swh_objects.append({"type": SNAPSHOT, "id": snapshot_id}) swh_ids = get_swh_persistent_ids(swh_objects, snapshot_context) note_header = "None" if len(release_note_lines) > 0: note_header = release_note_lines[0] release["note_header"] = note_header release["note_body"] = "\n".join(release_note_lines[1:]) heading = "Release - %s" % release["name"] if snapshot_context: context_found = "snapshot: %s" % snapshot_context["snapshot_id"] if origin_info: context_found = "origin: %s" % origin_info["url"] heading += " - %s" % context_found return render( request, "browse/release.html", { "heading": heading, "swh_object_id": swh_ids[0]["swh_id"], "swh_object_name": "Release", - "swh_object_metadata": release_data, + "swh_object_metadata": release_metadata, "release": release, "snapshot_context": snapshot_context, "show_actions_menu": True, "breadcrumbs": None, "vault_cooking": vault_cooking, "top_right_link": None, "swh_ids": swh_ids, }, ) diff --git a/swh/web/common/typing.py b/swh/web/common/typing.py index f0277e65..2d5c7396 100644 --- a/swh/web/common/typing.py +++ b/swh/web/common/typing.py @@ -1,154 +1,167 @@ # Copyright (C) 2020 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information from typing import Any, Dict, List, Optional, Union from typing_extensions import TypedDict from django.http import QueryDict QueryParameters = Union[Dict[str, Any], QueryDict] class OriginInfo(TypedDict): url: str """URL of the origin""" class OriginVisitInfo(TypedDict): date: str """date of the visit in iso format""" formatted_date: str """formatted date of the visit""" metadata: Dict[str, Any] """metadata associated to the visit""" origin: str """visited origin URL""" snapshot: str """snapshot identifier computed during the visit""" status: str """status of the visit ("ongoing", "full" or "partial") """ type: str """visit type (git, hg, debian, ...)""" url: str """URL to browse the snapshot""" visit: int """visit identifier""" class SnapshotBranchInfo(TypedDict): date: Optional[str] """"author date of branch heading revision""" directory: Optional[str] """directory associated to branch heading revision""" message: Optional[str] """message of branch heading revision""" name: Optional[str] """branch name""" revision: str """branch heading revision""" url: Optional[str] """optional browse URL (content, directory, ...) scoped to branch""" class SnapshotReleaseInfo(TypedDict): branch_name: str """branch name associated to release in snapshot""" date: str """release date""" directory: Optional[str] """optional directory associatd to the release""" id: str """release identifier""" message: str """release message""" name: str """release name""" target: str """release target""" target_type: str """release target_type""" url: Optional[str] """optional browse URL (content, directory, ...) scoped to release""" class SnapshotContext(TypedDict): branch: Optional[str] """optional branch name set when browsing snapshot int that scope""" branches: List[SnapshotBranchInfo] """list of snapshot branches (possibly truncated)""" branches_url: str """snapshot branches list browse URL""" is_empty: bool """indicates if the snapshot is empty""" origin_info: Optional[OriginInfo] """optional origin info associated to the snapshot""" origin_visits_url: Optional[str] """optional origin visits URL""" query_params: QueryParameters """common query parameters when browsing snapshot content""" release: Optional[str] """optional release name set when browsing snapshot int that scope""" release_id: Optional[str] """optional release identifier set when browsing snapshot int that scope""" releases: List[SnapshotReleaseInfo] """list of snapshot releases (possibly truncated)""" releases_url: str """snapshot releases list browse URL""" revision_id: Optional[str] """optional revision identifier set when browsing snapshot int that scope""" root_directory: Optional[str] """optional root directory identifier set when browsing snapshot content""" snapshot_id: str """snapshot identifier""" snapshot_sizes: Dict[str, int] """snapshot sizes grouped by branch target type""" snapshot_swhid: str """snapshot SWHID""" url_args: Dict[str, Any] """common URL arguments when browsing snapshot content""" visit_info: Optional[OriginVisitInfo] """optional origin visit info associated to the snapshot""" class SWHObjectMetadata(TypedDict, total=False): object_type: str origin_url: Optional[str] visit_date: Optional[str] visit_type: Optional[str] directory_url: Optional[str] revision_url: Optional[str] release_url: Optional[str] snapshot_url: Optional[str] class ContentMetadata(SWHObjectMetadata): sha1: str sha1_git: str sha256: str blake2s256: str content_url: str mimetype: str encoding: str size: str language: str licenses: str path: Optional[str] filename: Optional[str] directory: Optional[str] revision: Optional[str] release: Optional[str] snapshot: Optional[str] class DirectoryMetadata(SWHObjectMetadata): directory: str nb_files: int nb_dirs: int sum_file_sizes: str path: str revision: Optional[str] revision_found: Optional[bool] release: Optional[str] snapshot: Optional[str] + + +class ReleaseMetadata(SWHObjectMetadata): + release: str + author: str + author_url: str + date: str + name: str + synthetic: bool + target: str + target_type: str + target_url: str + snapshot: Optional[str] diff --git a/swh/web/templates/browse/release.html b/swh/web/templates/browse/release.html index e98ae8e7..de1cd187 100644 --- a/swh/web/templates/browse/release.html +++ b/swh/web/templates/browse/release.html @@ -1,30 +1,30 @@ {% extends "./browse.html" %} {% comment %} Copyright (C) 2017-2019 The Software Heritage developers See the AUTHORS file at the top-level directory of this distribution License: GNU Affero General Public License version 3, or any later version See top-level LICENSE file for more information {% endcomment %} {% load swh_templatetags %} {% block swh-browse-content %} {% include "includes/top-navigation.html" %}
Release {{ swh_object_metadata.name }} - created by {{ swh_object_metadata.author }} on {{ swh_object_metadata.date }} + created by {{ swh_object_metadata.author_url }} on {{ swh_object_metadata.date }}
 
{{ release.note_header }}
{{ release.note_body }}
Target: {{ release.target_link}} {% if release.directory_link %}
Directory: {{ release.directory_link}} {% endif %}
{% endblock %}