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 @@ -55,20 +55,12 @@ def _get_branch(branches, branch_name, snapshot_id): """ - Utility function to get a specific branch from a branches list. - Its purpose is to get the default HEAD branch as some software origin - (e.g those with svn type) does not have it. In that latter case, check - if there is a master branch instead and returns it. + Utility function to get a specific branch from a snapshot. + Returns None if the branch cannot be found. """ filtered_branches = [b for b in branches if b["name"] == branch_name] if filtered_branches: return filtered_branches[0] - elif branch_name == "HEAD": - filtered_branches = [b for b in branches if b["name"].endswith("master")] - if filtered_branches: - return filtered_branches[0] - elif branches: - return branches[0] else: # case where a large branches list has been truncated snp = archive.lookup_snapshot( @@ -88,8 +80,8 @@ def _get_release(releases, release_name, snapshot_id): """ - Utility function to get a specific release from a releases list. - Returns None if the release can not be found in the list. + Utility function to get a specific release from a snapshot. + Returns None if the release cannot be found. """ filtered_releases = [r for r in releases if r["name"] == release_name] if filtered_releases: @@ -109,7 +101,7 @@ snapshot_id, branches_from=release_name, branches_count=1, - target_types=["release"], + target_types=["release", "alias"], ) _, snp_release, _ = process_snapshot_branches(snp) if snp_release and snp_release[0]["name"] == release_name: @@ -525,6 +517,7 @@ query_params["path"] = path if snapshot_total_size and revision_id is not None: + # browse specific revision for a snapshot requested revision = archive.lookup_revision(revision_id) root_directory = revision["directory"] branches.append( @@ -540,6 +533,7 @@ ) query_params["revision"] = revision_id elif snapshot_total_size and release_name: + # browse specific release for a snapshot requested release = _get_release(releases, release_name, snapshot_id) if release is None: _branch_not_found( @@ -552,28 +546,70 @@ visit_id, ) else: - root_directory = release["directory"] - revision_id = release["target"] + if release["target_type"] == "revision": + revision = archive.lookup_revision(release["target"]) + root_directory = revision["directory"] + revision_id = release["target"] + elif release["target_type"] == "directory": + root_directory = release["target"] release_id = release["id"] query_params["release"] = release_name elif snapshot_total_size: + head = aliases.get("HEAD") if branch_name: + # browse specific branch for a snapshot requested query_params["branch"] = branch_name - branch = _get_branch(branches, branch_name or "HEAD", snapshot_id) - if branch is None: - _branch_not_found( - "branch", - branch_name, - snapshot_id, - snapshot_sizes, - origin_info, - timestamp, - visit_id, - ) - else: + branch = _get_branch(branches, branch_name, snapshot_id) + if branch is None: + _branch_not_found( + "branch", + branch_name, + snapshot_id, + snapshot_sizes, + origin_info, + timestamp, + visit_id, + ) + else: + branch_name = branch["name"] + revision_id = branch["revision"] + root_directory = branch["directory"] + elif head is not None: + # otherwise, browse branch targeted by the HEAD alias if it exists + if head["target_type"] == "revision": + # HEAD alias targets a revision + head_rev = archive.lookup_revision(head["target"]) + branch_name = "HEAD" + revision_id = head_rev["id"] + root_directory = head_rev["directory"] + else: + # HEAD alias targets a release + release_name = archive.lookup_release(head["target"])["name"] + head_rel = _get_release(releases, release_name, snapshot_id) + if head_rel["target_type"] == "revision": + revision = archive.lookup_revision(head_rel["target"]) + root_directory = revision["directory"] + revision_id = head_rel["target"] + elif head_rel["target_type"] == "directory": + root_directory = head_rel["target"] + release_id = head_rel["id"] + elif branches: + # fallback to browse first branch otherwise + branch = branches[0] branch_name = branch["name"] revision_id = branch["revision"] root_directory = branch["directory"] + elif releases: + # fallback to browse last release otherwise + release = releases[-1] + if release["target_type"] == "revision": + revision = archive.lookup_revision(release["target"]) + root_directory = revision["directory"] + revision_id = release["target"] + elif release["target_type"] == "directory": + root_directory = release["target"] + release_id = release["id"] + release_name = release["name"] for b in branches: branch_query_params = dict(query_params) diff --git a/swh/web/browse/views/directory.py b/swh/web/browse/views/directory.py --- a/swh/web/browse/views/directory.py +++ b/swh/web/browse/views/directory.py @@ -187,7 +187,11 @@ heading += " - %s" % dir_path top_right_link = None - if snapshot_context is not None and not snapshot_context["is_empty"]: + if ( + snapshot_context is not None + and not snapshot_context["is_empty"] + and snapshot_context["revision_id"] is not None + ): history_url = reverse( "browse-revision-log", url_args={"sha1_git": snapshot_context["revision_id"]}, diff --git a/swh/web/templates/includes/top-navigation.html b/swh/web/templates/includes/top-navigation.html --- a/swh/web/templates/includes/top-navigation.html +++ b/swh/web/templates/includes/top-navigation.html @@ -67,7 +67,7 @@
{% if snapshot_context.releases %} {% for r in snapshot_context.releases %} - {% if r.target_type == 'revision' %} + {% if r.target_type == 'revision' or r.target_type == 'directory' %}
  • {% if r.alias %} diff --git a/swh/web/tests/browse/test_snapshot_context.py b/swh/web/tests/browse/test_snapshot_context.py --- a/swh/web/tests/browse/test_snapshot_context.py +++ b/swh/web/tests/browse/test_snapshot_context.py @@ -5,6 +5,9 @@ import random +from swh.model.hashutil import hash_to_bytes +from swh.model.model import ObjectType as ModelObjectType +from swh.model.model import Release, Snapshot, SnapshotBranch, TargetType from swh.model.swhids import ObjectType from swh.web.browse.snapshot_context import ( _get_release, @@ -404,3 +407,101 @@ revision_info["committer_date"] ) return revision_info + + +def test_get_snapshot_context_revision_release(archive_data, revision): + release_name = "v1.0.0" + release = Release( + name=release_name.encode(), + message=f"release {release_name}".encode(), + target=hash_to_bytes(revision), + target_type=ModelObjectType.REVISION, + synthetic=True, + ) + archive_data.release_add([release]) + + snapshot = Snapshot( + branches={ + b"HEAD": SnapshotBranch( + target=release_name.encode(), target_type=TargetType.ALIAS + ), + release_name.encode(): SnapshotBranch( + target=release.id, target_type=TargetType.RELEASE + ), + }, + ) + archive_data.snapshot_add([snapshot]) + + snapshot_no_head = Snapshot( + branches={ + release_name.encode(): SnapshotBranch( + target=release.id, target_type=TargetType.RELEASE + ), + }, + ) + archive_data.snapshot_add([snapshot_no_head]) + + revision_data = archive_data.revision_get(revision) + + for params in ( + {"snapshot_id": snapshot.id.hex()}, + {"snapshot_id": snapshot.id.hex(), "release_name": release_name}, + {"snapshot_id": snapshot_no_head.id.hex()}, + ): + + snapshot_context = get_snapshot_context(**params) + + assert snapshot_context["branches"] == [] + assert snapshot_context["releases"] != [] + assert snapshot_context["release"] == release_name + assert snapshot_context["release_id"] == release.id.hex() + assert snapshot_context["revision_id"] == revision + assert snapshot_context["root_directory"] == revision_data["directory"] + + +def test_get_snapshot_context_directory_release(archive_data, directory): + release_name = "v1.0.0" + release = Release( + name=release_name.encode(), + message=f"release {release_name}".encode(), + target=hash_to_bytes(directory), + target_type=ModelObjectType.DIRECTORY, + synthetic=True, + ) + archive_data.release_add([release]) + + snapshot = Snapshot( + branches={ + b"HEAD": SnapshotBranch( + target=release_name.encode(), target_type=TargetType.ALIAS + ), + release_name.encode(): SnapshotBranch( + target=release.id, target_type=TargetType.RELEASE + ), + }, + ) + archive_data.snapshot_add([snapshot]) + + snapshot_no_head = Snapshot( + branches={ + release_name.encode(): SnapshotBranch( + target=release.id, target_type=TargetType.RELEASE + ), + }, + ) + archive_data.snapshot_add([snapshot_no_head]) + + for params in ( + {"snapshot_id": snapshot.id.hex()}, + {"snapshot_id": snapshot.id.hex(), "release_name": release_name}, + {"snapshot_id": snapshot_no_head.id.hex()}, + ): + + snapshot_context = get_snapshot_context(**params) + + assert snapshot_context["branches"] == [] + assert snapshot_context["releases"] != [] + assert snapshot_context["release"] == release_name + assert snapshot_context["release_id"] == release.id.hex() + assert snapshot_context["revision_id"] is None + assert snapshot_context["root_directory"] == directory