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 @@ -63,6 +63,15 @@ $('.swh-popover-toggler').popover('hide'); }); + $('#swh-branch-name-search').keyup(function(e) { + if (e.code === 'Enter') { + // On return key press event + var searchParams = new URLSearchParams(window.location.search); + searchParams.set('branch-name-include', $(this).val().trim()); + window.location.search = searchParams.toString(); + } + }); + $('body').on('click', e => { if ($(e.target).parents('.swh-popover').length) { e.stopPropagation(); 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 @@ -83,5 +83,32 @@ cy.get('#swh-browse-snapshot-releases-nav-link') .should('have.class', 'disabled'); }); +}); + +describe('Test browse branches', function() { + beforeEach(function() { + const url = `${this.Urls.browse_origin_branches()}?origin_url=${this.origin[1].url}`; + cy.visit(url); + }); + + it('should have the master branch in the list', function() { + cy.get('table').contains('td', 'master').should('be.visible'); + }); + + it('search inside branches', function() { + cy.get('#swh-branch-name-search').type('mas{enter}'); + cy.location('search') + .should('include', 'branch-name-include=mas'); + + cy.get('table').contains('td', 'master').should('be.visible'); + + cy.get('#swh-branch-name-search').should('have.value', 'mas'); + }); + + it('search non existing branch name', function() { + cy.get('#swh-branch-name-search').type('randomstringabc{enter}'); + + cy.get('table').contains('td', 'The list of branches is empty').should('be.visible'); + }); }); diff --git a/swh/web/browse/snapshot_context.py b/swh/web/browse/snapshot_context.py --- a/swh/web/browse/snapshot_context.py +++ b/swh/web/browse/snapshot_context.py @@ -1214,7 +1214,7 @@ def browse_snapshot_branches( - request, snapshot_id=None, origin_url=None, timestamp=None + request, snapshot_id=None, origin_url=None, timestamp=None, branchname_include=None ): """ Django view implementation for browsing a list of branches in a snapshot @@ -1247,9 +1247,11 @@ branches_from, PER_PAGE + 1, target_types=["revision", "alias"], + branch_name_include_substring=branchname_include, ) - - displayed_branches, _, _ = process_snapshot_branches(snapshot) + displayed_branches = [] + if snapshot: + displayed_branches, _, _ = process_snapshot_branches(snapshot) for branch in displayed_branches: rev_query_params = {} @@ -1290,7 +1292,7 @@ browse_view_name, url_args=url_args, query_params=query_params ) - if snapshot["next_branch"] is not None: + if snapshot and snapshot["next_branch"] is not None: query_params_next = dict(query_params) next_branch = displayed_branches[-1]["name"] del displayed_branches[-1] @@ -1318,6 +1320,7 @@ "prev_branches_url": prev_branches_url, "next_branches_url": next_branches_url, "snapshot_context": snapshot_context, + "search_string": branchname_include or "", }, ) @@ -1352,7 +1355,6 @@ PER_PAGE + 1, target_types=["release", "alias"], ) - _, displayed_releases, _ = process_snapshot_branches(snapshot) for release in displayed_releases: 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 @@ -161,6 +161,7 @@ origin_url=request.GET.get("origin_url"), snapshot_id=request.GET.get("snapshot"), timestamp=request.GET.get("timestamp"), + branchname_include=request.GET.get("branch-name-include"), ) diff --git a/swh/web/common/archive.py b/swh/web/common/archive.py --- a/swh/web/common/archive.py +++ b/swh/web/common/archive.py @@ -1069,6 +1069,7 @@ ) -> Dict[str, Any]: """Return information about a snapshot, aka the list of named branches found during a specific visit of an origin. + Raises NotFoundException if the given snapshot_id is missing Args: snapshot_id: sha1 identifier of the snapshot @@ -1090,6 +1091,9 @@ A dict filled with the snapshot content. """ snapshot_id_bin = _to_sha1_bin(snapshot_id) + if storage.snapshot_missing([snapshot_id_bin]): + raise NotFoundExc(f"Snapshot with id {snapshot_id} not found!") + partial_branches = storage.snapshot_get_branches( snapshot_id_bin, branches_from.encode(), @@ -1100,10 +1104,9 @@ else None, branch_name_exclude_prefix.encode() if branch_name_exclude_prefix else None, ) - if not partial_branches: - raise NotFoundExc(f"Snapshot with id {snapshot_id} not found!") - - return converters.from_partial_branches(partial_branches) + return ( + converters.from_partial_branches(partial_branches) if partial_branches else None + ) def lookup_latest_origin_snapshot( diff --git a/swh/web/templates/browse/branches.html b/swh/web/templates/browse/branches.html --- a/swh/web/templates/browse/branches.html +++ b/swh/web/templates/browse/branches.html @@ -11,8 +11,16 @@ {% load swh_templatetags %} {% block swh-browse-content %} -{% if displayed_branches|length > 0 %}
+
+
+ +
+
@@ -23,54 +31,59 @@ - {% for branch in displayed_branches %} - - + {% if displayed_branches|length > 0 %} + {% for branch in displayed_branches %} + + + + + + + {% endfor %} + {% else %} + - - - {% endfor %} + {% endif %}
- - {% if branch.alias %} - - {% else %} - - {% endif %} - {{ branch.name }} - -
+ + {% if branch.alias %} + + {% else %} + + {% endif %} + {{ branch.name }} + + + + {{ branch.revision|slice:":7" }} + + + {{ branch.message }} + + {{ branch.date }} +
- - {{ branch.revision|slice:":7" }} - - - {{ branch.message }} - - {{ branch.date }} + The list of branches is empty!
- -{% else %} - The list of branches is empty ! -{% endif %} {% endblock %} + {% block swh-browse-after-content %} -{% if prev_branches_url or next_branches_url %} - + {% endif %} {% endblock %} diff --git a/swh/web/tests/common/test_archive.py b/swh/web/tests/common/test_archive.py --- a/swh/web/tests/common/test_archive.py +++ b/swh/web/tests/common/test_archive.py @@ -1069,6 +1069,13 @@ assert resolved_alias["target"] is not None +@given(revision()) +def test_lookup_snapshot_missing(revision): + rev_id = hash_to_bytes(revision) + with pytest.raises(NotFoundExc): + archive.lookup_snapshot(hash_to_hex(rev_id)) + + @given(revision()) def test_lookup_snapshot_branch_names_filtering(archive_data, revision): rev_id = hash_to_bytes(revision)