diff --git a/docs/uri-scheme-browse-directory.rst b/docs/uri-scheme-browse-directory.rst --- a/docs/uri-scheme-browse-directory.rst +++ b/docs/uri-scheme-browse-directory.rst @@ -1,7 +1,41 @@ Directory ^^^^^^^^^ -.. http:get:: /browse/directory/(sha1_git)/[(path)/] +.. http:get:: /browse/directory/(sha1_git)/ + + HTML view for browsing the content of a directory reachable from + the provided root one (including itself) identified by its **sha1_git** value. + + The content of the directory is first sorted in lexicographical order + and the sub-directories are displayed before the regular files. + + The view enables to navigate from the requested directory to + directories reachable from it in a recursive way but also + up to the root directory. + A breadcrumb located in the top part of the view allows + to keep track of the paths navigated so far. + + :param string sha1_git: hexadecimal representation for the **sha1_git** identifier + of the directory to browse + :query string path: optional parameter used to specify the path of a directory + reachable from the provided root one + :statuscode 200: no error + :statuscode 400: an invalid **sha1_git** value has been provided + :statuscode 404: requested directory can not be found in the archive + + **Examples:** + + .. parsed-literal:: + + :swh_web_browse:`directory/977fc4b98c0e85816348cebd3b12026407c368b6/` + :swh_web_browse:`directory/9650ed370c0330d2cd2b6fd1e9febf649ffe538d/?path=kernel/sched` + + +.. http:get:: /browse/directory/(sha1_git)/(path)/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/directory/(sha1_git)/` instead. HTML view for browsing the content of a directory reachable from the provided root one (including itself) identified by its **sha1_git** value. diff --git a/docs/uri-scheme-browse.rst b/docs/uri-scheme-browse.rst --- a/docs/uri-scheme-browse.rst +++ b/docs/uri-scheme-browse.rst @@ -21,7 +21,7 @@ * :http:get:`/browse/content/[(algo_hash):](hash)/`: Display a content * :http:get:`/browse/content/[(algo_hash):](hash)/raw/`: Get / Download content raw data - * :http:get:`/browse/directory/(sha1_git)/[(path)/]`: Browse the content of a directory + * :http:get:`/browse/directory/(sha1_git)/`: Browse the content of a directory * :http:get:`/browse/person/(person_id)/`: Information on a person * :http:get:`/browse/revision/(sha1_git)/`: Browse a revision * :http:get:`/browse/revision/(sha1_git)/log/`: Browse history log heading to a revision diff --git a/swh/web/assets/src/bundles/webapp/xss-filtering.js b/swh/web/assets/src/bundles/webapp/xss-filtering.js --- a/swh/web/assets/src/bundles/webapp/xss-filtering.js +++ b/swh/web/assets/src/bundles/webapp/xss-filtering.js @@ -1,5 +1,5 @@ /** - * Copyright (C) 2019 The Software Heritage developers + * Copyright (C) 2019-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 @@ -31,8 +31,8 @@ // used internal endpoint as image url to possibly get the image data // from the archive content - let url = Urls.browse_directory_resolve_content_path(swhObjectMetadata.directory, - data.attrValue); + let url = Urls.browse_directory_resolve_content_path(swhObjectMetadata.directory); + url += `?path=${data.attrValue}`; data.attrValue = url; } }); diff --git a/swh/web/browse/views/content.py b/swh/web/browse/views/content.py --- a/swh/web/browse/views/content.py +++ b/swh/web/browse/views/content.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017-2019 The Software Heritage developers +# 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 @@ -268,9 +268,10 @@ ) breadcrumbs.append({"name": root_dir[:7], "url": dir_url}) for pi in path_info: + query_params["path"] = pi["path"] dir_url = reverse( "browse-directory", - url_args={"sha1_git": root_dir, "path": pi["path"]}, + url_args={"sha1_git": root_dir}, query_params=query_params, ) breadcrumbs.append({"name": pi["name"], "url": dir_url}) 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 @@ -24,19 +24,7 @@ from swh.web.common.utils import reverse, gen_path_info -@browse_route( - r"directory/(?P[0-9a-f]+)/", - r"directory/(?P[0-9a-f]+)/(?P.+)/", - view_name="browse-directory", - checksum_args=["sha1_git"], -) -def directory_browse(request, sha1_git, path=None): - """Django view for browsing the content of a directory identified - by its sha1_git value. - - The url that points to it is - :http:get:`/browse/directory/(sha1_git)/[(path)/]` - """ +def _directory_browse(request, sha1_git, path=None): root_sha1_git = sha1_git try: if path: @@ -92,8 +80,8 @@ "name": pi["name"], "url": reverse( "browse-directory", - url_args={"sha1_git": root_sha1_git, "path": pi["path"]}, - query_params=query_params, + url_args={"sha1_git": root_sha1_git}, + query_params={"path": pi["path"], **query_params}, ), } ) @@ -110,8 +98,8 @@ else: d["url"] = reverse( "browse-directory", - url_args={"sha1_git": root_sha1_git, "path": path + d["name"]}, - query_params=query_params, + url_args={"sha1_git": root_sha1_git}, + query_params={"path": path + d["name"], **query_params}, ) sum_file_sizes = 0 @@ -187,17 +175,47 @@ @browse_route( - r"directory/resolve/content-path/(?P[0-9a-f]+)/(?P.+)/", + r"directory/(?P[0-9a-f]+)/", + view_name="browse-directory", + checksum_args=["sha1_git"], +) +def directory_browse(request, sha1_git): + """Django view for browsing the content of a directory identified + by its sha1_git value. + + The url that points to it is + :http:get:`/browse/directory/(sha1_git)/` + """ + return _directory_browse(request, sha1_git, request.GET.get("path")) + + +@browse_route( + r"directory/(?P[0-9a-f]+)/(?P.+)/", + view_name="browse-directory-legacy", + checksum_args=["sha1_git"], +) +def directory_browse_legacy(request, sha1_git, path): + """Django view for browsing the content of a directory identified + by its sha1_git value. + + The url that points to it is + :http:get:`/browse/directory/(sha1_git)/(path)/` + """ + return _directory_browse(request, sha1_git, path) + + +@browse_route( + r"directory/resolve/content-path/(?P[0-9a-f]+)/", view_name="browse-directory-resolve-content-path", checksum_args=["sha1_git"], ) -def _directory_resolve_content_path(request, sha1_git, path): +def _directory_resolve_content_path(request, sha1_git): """ Internal endpoint redirecting to data url for a specific file path relative to a root directory. """ try: - path = os.path.normpath(path) + path = os.path.normpath(request.GET.get("path")) if not path.startswith("../"): dir_info = service.lookup_directory_with_path(sha1_git, path) if dir_info["type"] == "file": diff --git a/swh/web/browse/views/revision.py b/swh/web/browse/views/revision.py --- a/swh/web/browse/views/revision.py +++ b/swh/web/browse/views/revision.py @@ -288,11 +288,10 @@ @browse_route( r"revision/(?P[0-9a-f]+)/", - r"revision/(?P[0-9a-f]+)/(?P.+)/", view_name="browse-revision", checksum_args=["sha1_git"], ) -def revision_browse(request, sha1_git, extra_path=None): +def revision_browse(request, sha1_git): """ Django view that produces an HTML display of a revision identified by its id. diff --git a/swh/web/tests/browse/views/test_content.py b/swh/web/tests/browse/views/test_content.py --- a/swh/web/tests/browse/views/test_content.py +++ b/swh/web/tests/browse/views/test_content.py @@ -167,7 +167,9 @@ for p in path_info: dir_url = reverse( - "browse-directory", url_args={"sha1_git": root_dir_sha1, "path": p["path"]} + "browse-directory", + url_args={"sha1_git": root_dir_sha1}, + query_params={"path": p["path"]}, ) assert_contains(resp, '' + p["name"] + "") diff --git a/swh/web/tests/browse/views/test_directory.py b/swh/web/tests/browse/views/test_directory.py --- a/swh/web/tests/browse/views/test_directory.py +++ b/swh/web/tests/browse/views/test_directory.py @@ -80,10 +80,11 @@ files = [e for e in directory_entries if e["type"] == "file"] url_args = {"sha1_git": root_directory_sha1} + query_params = {} if path: - url_args["path"] = path + query_params["path"] = path - url = reverse("browse-directory", url_args=url_args) + url = reverse("browse-directory", url_args=url_args, query_params=query_params) root_dir_url = reverse( "browse-directory", url_args={"sha1_git": root_directory_sha1} @@ -108,7 +109,8 @@ dir_path = "%s/%s" % (path, d["name"]) dir_url = reverse( "browse-directory", - url_args={"sha1_git": root_directory_sha1, "path": dir_path}, + url_args={"sha1_git": root_directory_sha1}, + query_params={"path": dir_path}, ) assert_contains(resp, dir_url) @@ -134,7 +136,8 @@ for p in path_info: dir_url = reverse( "browse-directory", - url_args={"sha1_git": root_directory_sha1, "path": p["path"]}, + url_args={"sha1_git": root_directory_sha1}, + query_params={"path": p["path"]}, ) assert_contains(resp, '%s' % (dir_url, p["name"]))