diff --git a/assets/src/bundles/browse/browse-utils.js b/assets/src/bundles/browse/browse-utils.js --- a/assets/src/bundles/browse/browse-utils.js +++ b/assets/src/bundles/browse/browse-utils.js @@ -83,7 +83,8 @@ if (window.location.pathname === Urls.browse_origin_visits()) { $('#swh-browse-origin-visits-nav-link').addClass('active'); } else if (window.location.pathname === Urls.browse_origin_branches() || - window.location.pathname === Urls.browse_snapshot_branches()) { + window.location.pathname === Urls.browse_snapshot_branches() || + window.location.pathname.endsWith('branches/')) { $('#swh-browse-snapshot-branches-nav-link').addClass('active'); } else if (window.location.pathname === Urls.browse_origin_releases() || window.location.pathname === Urls.browse_snapshot_releases()) { diff --git a/cypress/integration/origin-browse.spec.js b/cypress/integration/origin-browse.spec.js --- a/cypress/integration/origin-browse.spec.js +++ b/cypress/integration/origin-browse.spec.js @@ -21,7 +21,7 @@ .click(); cy.location('pathname') - .should('eq', this.Urls.browse_origin_branches()); + .should('eq', this.Urls.browse_snapshot_branches(this.origin[1].snapshot)); cy.location('search') .should('eq', `?origin_url=${this.origin[1].url}`); diff --git a/docs/uri-scheme-browse-origin.rst b/docs/uri-scheme-browse-origin.rst --- a/docs/uri-scheme-browse-origin.rst +++ b/docs/uri-scheme-browse-origin.rst @@ -646,6 +646,10 @@ """"""""""""""" .. http:get:: /browse/origin/branches/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/snapshot/branches/` instead. HTML view that produces a display of the list of branches found during the latest full visit of a software origin. @@ -682,7 +686,7 @@ :deprecated: .. warning:: - That endpoint is deprecated, use :http:get:`/browse/origin/branches/` instead. + That endpoint is deprecated, use :http:get:`/browse/snapshot/branches/` instead. HTML view that produces a display of the list of branches found during the latest full visit of a software origin. diff --git a/docs/uri-scheme-browse-snapshot.rst b/docs/uri-scheme-browse-snapshot.rst --- a/docs/uri-scheme-browse-snapshot.rst +++ b/docs/uri-scheme-browse-snapshot.rst @@ -232,6 +232,29 @@ Snapshot branches """"""""""""""""" +.. http:get:: /browse/snapshot/branches/ + + HTML view that produces a display of the list of branches collected in a snapshot. + An origin URL must be given as a query parameter. + + :query string origin_url: specify the origin from which to retrieve the snapshot and branches + :query string timestamp: optional; an ISO 8601 datetime string to parse in order to + find the closest visit + :name_include: optional; to filter branches by name + + :statuscode 200: no error + :statuscode 400: origin_url parameter is missing + :statuscode 404: requested origin is either missing or has no associated snapshots + + **Examples:** + + .. parsed-literal:: + + :swh_web_browse:`snapshot/branches?origin_url=https://github.com/python/cpython` + :swh_web_browse:`snapshot/branches/?origin_url=https://github.com/python/cpython×tamp=2021-01-23T22:24:10Z` + :swh_web_browse:`snapshot/branches/?origin_url=https://github.com/python/cpython&name_include=v2` + + .. http:get:: /browse/snapshot/(snapshot_id)/branches/ HTML view that produces a display of the list of branches diff --git a/swh/web/browse/views/origin.py b/swh/web/browse/views/origin.py --- a/swh/web/browse/views/origin.py +++ b/swh/web/browse/views/origin.py @@ -8,7 +8,6 @@ from swh.web.browse.browseurls import browse_route from swh.web.browse.snapshot_context import ( - browse_snapshot_branches, browse_snapshot_content, browse_snapshot_directory, browse_snapshot_releases, @@ -155,19 +154,16 @@ r"origin/branches/", view_name="browse-origin-branches", ) def origin_branches_browse(request): - """Django view that produces an HTML display of the list of branches + """ + This route is deprecated; use http:get:`/browse/snapshot/branches` instead + + Django view that produces an HTML display of the list of branches associated to an origin for a given visit. The URL that points to it is :http:get:`/browse/origin/branches/` """ - return browse_snapshot_branches( - request, - origin_url=request.GET.get("origin_url"), - snapshot_id=request.GET.get("snapshot"), - timestamp=request.GET.get("timestamp"), - branch_name_include=request.GET.get("name_include"), - ) + return redirect_to_new_route(request, "browse-snapshot-branches") @browse_route( @@ -176,7 +172,10 @@ view_name="browse-origin-branches-legacy", ) def origin_branches_browse_legacy(request, origin_url, timestamp=None): - """Django view that produces an HTML display of the list of branches + """ + This route is deprecated; use http:get:`/browse/snapshot/branches` instead + + Django view that produces an HTML display of the list of branches associated to an origin for a given visit. The URLs that point to it are @@ -184,12 +183,7 @@ :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/branches/` """ - return browse_snapshot_branches( - request, - origin_url=origin_url, - snapshot_id=request.GET.get("snapshot"), - timestamp=timestamp, - ) + return redirect_to_new_route(request, "browse-snapshot-branches") @browse_route( diff --git a/swh/web/browse/views/snapshot.py b/swh/web/browse/views/snapshot.py --- a/swh/web/browse/views/snapshot.py +++ b/swh/web/browse/views/snapshot.py @@ -161,17 +161,36 @@ @browse_route( r"snapshot/(?P[0-9a-f]+)/branches/", + r"snapshot/branches/", view_name="browse-snapshot-branches", checksum_args=["snapshot_id"], ) -def snapshot_branches_browse(request, snapshot_id): +def snapshot_branches_browse(request, snapshot_id=None): """Django view that produces an HTML display of the list of releases collected in a snapshot. - The url that points to it is - :http:get:`/browse/snapshot/(snapshot_id)/branches/` + The URLs that point to it are + :http:get:`/browse/snapshot/(snapshot_id)/branches/` and + :http:get:`/browse/snapshot/branches/` """ - return browse_snapshot_branches(request, snapshot_id=snapshot_id) + if snapshot_id is None: + # This case happens when redirected from /origin/branches + snapshot_id = get_snapshot_from_request(request) + # Redirect to the same route with snapshot_id + return redirect( + reverse( + "browse-snapshot-branches", + url_args={"snapshot_id": snapshot_id}, + query_params=request.GET, + ), + ) + return browse_snapshot_branches( + request, + snapshot_id=snapshot_id, + origin_url=request.GET.get("origin_url"), + timestamp=request.GET.get("timestamp"), + branch_name_include=request.GET.get("name_include"), + ) @browse_route( diff --git a/swh/web/tests/browse/views/test_origin.py b/swh/web/tests/browse/views/test_origin.py --- a/swh/web/tests/browse/views/test_origin.py +++ b/swh/web/tests/browse/views/test_origin.py @@ -5,7 +5,6 @@ import random import re -import string from hypothesis import given import pytest @@ -31,7 +30,7 @@ parse_iso8601_date_to_utc, reverse, ) -from swh.web.tests.data import get_content, random_sha1 +from swh.web.tests.data import get_content from swh.web.tests.django_asserts import assert_contains, assert_not_contains from swh.web.tests.strategies import new_origin, new_snapshot, visit_dates from swh.web.tests.utils import check_html_get_response @@ -396,21 +395,6 @@ ) -def test_origin_branches(client, archive_data, origin): - origin_visits = archive_data.origin_visit_get(origin["url"]) - - visit = origin_visits[-1] - snapshot = archive_data.snapshot_get(visit["snapshot"]) - snapshot_sizes = archive_data.snapshot_count_branches(snapshot["id"]) - snapshot_content = process_snapshot_branches(snapshot) - - _origin_branches_test_helper(client, origin, snapshot_content, snapshot_sizes) - - _origin_branches_test_helper( - client, origin, snapshot_content, snapshot_sizes, snapshot_id=visit["snapshot"] - ) - - def test_origin_releases(client, archive_data, origin): origin_visits = archive_data.origin_visit_get(origin["url"]) @@ -832,7 +816,6 @@ for browse_context in ( "content", "directory", - "branches", "releases", "visits", ): @@ -846,7 +829,7 @@ @given(new_origin()) -@pytest.mark.parametrize("browse_context", ["log"]) +@pytest.mark.parametrize("browse_context", ["log", "branches"]) def test_origin_view_redirects(client, browse_context, new_origin): query_params = {"origin_url": new_origin.url} url = reverse(f"browse-origin-{browse_context}", query_params=query_params) @@ -858,7 +841,7 @@ @given(new_origin()) -@pytest.mark.parametrize("browse_context", ["log"]) +@pytest.mark.parametrize("browse_context", ["log", "branches"]) def test_origin_view_legacy_redirects(client, browse_context, new_origin): params = {"origin_url": new_origin.url, "timestamp": "2021-01-23T22:24:10Z"} url = reverse( @@ -1155,51 +1138,6 @@ assert_not_contains(resp, "swh-metadata-popover") -def _origin_branches_test_helper( - client, origin_info, origin_snapshot, snapshot_sizes, snapshot_id=None -): - query_params = {"origin_url": origin_info["url"], "snapshot": snapshot_id} - - url = reverse("browse-origin-branches", query_params=query_params) - - resp = check_html_get_response( - client, url, status_code=200, template_used="browse/branches.html" - ) - - origin_branches = origin_snapshot[0] - origin_releases = origin_snapshot[1] - - origin_branches_url = reverse("browse-origin-branches", query_params=query_params) - - assert_contains(resp, f'href="{escape(origin_branches_url)}"') - assert_contains(resp, f"Branches ({snapshot_sizes['revision']})") - - origin_releases_url = reverse("browse-origin-releases", query_params=query_params) - - nb_releases = len(origin_releases) - if nb_releases > 0: - assert_contains(resp, f'href="{escape(origin_releases_url)}">') - assert_contains(resp, f"Releases ({snapshot_sizes['release']})") - - assert_contains(resp, '' % escape(browse_branch_url)) - - browse_revision_url = reverse( - "browse-revision", - url_args={"sha1_git": branch["revision"]}, - query_params=query_params, - ) - assert_contains(resp, '' % escape(browse_revision_url)) - - _check_origin_link(resp, origin_info["url"]) - - def _origin_releases_test_helper( client, origin_info, origin_snapshot, snapshot_sizes, snapshot_id=None ): @@ -1246,56 +1184,6 @@ _check_origin_link(resp, origin_info["url"]) -@given( - new_origin(), visit_dates(), -) -def test_origin_branches_pagination_with_alias( - client, archive_data, mocker, release, revisions_list, new_origin, visit_dates, -): - """ - When a snapshot contains a branch or a release alias, pagination links - in the branches / releases view should be displayed. - """ - revisions = revisions_list(size=10) - mocker.patch("swh.web.browse.snapshot_context.PER_PAGE", len(revisions) / 2) - snp_dict = {"branches": {}, "id": hash_to_bytes(random_sha1())} - for i in range(len(revisions)): - branch = "".join(random.choices(string.ascii_lowercase, k=8)) - snp_dict["branches"][branch.encode()] = { - "target_type": "revision", - "target": hash_to_bytes(revisions[i]), - } - release_name = "".join(random.choices(string.ascii_lowercase, k=8)) - snp_dict["branches"][b"RELEASE_ALIAS"] = { - "target_type": "alias", - "target": release_name.encode(), - } - snp_dict["branches"][release_name.encode()] = { - "target_type": "release", - "target": hash_to_bytes(release), - } - archive_data.origin_add([new_origin]) - archive_data.snapshot_add([Snapshot.from_dict(snp_dict)]) - visit = archive_data.origin_visit_add( - [OriginVisit(origin=new_origin.url, date=visit_dates[0], type="git",)] - )[0] - visit_status = OriginVisitStatus( - origin=new_origin.url, - visit=visit.visit, - date=now(), - status="full", - snapshot=snp_dict["id"], - ) - archive_data.origin_visit_status_add([visit_status]) - - url = reverse("browse-origin-branches", query_params={"origin_url": new_origin.url}) - - resp = check_html_get_response( - client, url, status_code=200, template_used="browse/branches.html" - ) - assert_contains(resp, '