diff --git a/cypress/integration/code-highlighting.spec.js b/cypress/integration/code-highlighting.spec.js --- a/cypress/integration/code-highlighting.spec.js +++ b/cypress/integration/code-highlighting.spec.js @@ -18,7 +18,7 @@ describe('Code highlighting tests', function() { before(function() { origin = this.origin[0]; - url = this.Urls.browse_origin_content(origin.url, origin.content[0].path); + url = `${this.Urls.browse_origin_content(origin.url)}?path=${origin.content[0].path}`; }); it('should highlight source code and add line numbers', function() { diff --git a/cypress/integration/content-display.spec.js b/cypress/integration/content-display.spec.js --- a/cypress/integration/content-display.spec.js +++ b/cypress/integration/content-display.spec.js @@ -11,7 +11,7 @@ describe('Test File Rendering', function() { before(function() { origin = this.origin[0]; - url = this.Urls.browse_origin_content(origin.url, origin.content[0].path); + url = `${this.Urls.browse_origin_content(origin.url)}?path=${origin.content[0].path}`; }); beforeEach(function() { @@ -51,7 +51,7 @@ for (let i = 2; i < splittedPath.length; ++i) { const subDirPath = splittedPath.slice(1, i).join('/'); - const subDirUrl = this.Urls.browse_origin_directory(origin.url, subDirPath); + const subDirUrl = `${this.Urls.browse_origin_directory(origin.url)}?path=${subDirPath}`; cy.get(`a[href='${subDirUrl}']`) .should('be.visible'); diff --git a/cypress/integration/directory.spec.js b/cypress/integration/directory.spec.js --- a/cypress/integration/directory.spec.js +++ b/cypress/integration/directory.spec.js @@ -67,7 +67,7 @@ .click(); cy.url() - .should('include', url + dirs[0]['name']); + .should('include', `${url}?path=${dirs[0]['name']}`); cy.get('.swh-directory-table') .should('be.visible'); diff --git a/cypress/integration/language-select.spec.js b/cypress/integration/language-select.spec.js --- a/cypress/integration/language-select.spec.js +++ b/cypress/integration/language-select.spec.js @@ -17,7 +17,7 @@ describe('Test Content Language Select', function() { before(function() { origin = this.origin[0]; - contentWithLanguageInfo = this.Urls.browse_origin_content(origin.url, origin.content[1].path); + contentWithLanguageInfo = `${this.Urls.browse_origin_content(origin.url)}?path=${origin.content[1].path}`; contentWithoutLanguageInfo = this.Urls.browse_content(`sha1_git:${origin.content[1].sha1git}`); }); @@ -66,7 +66,7 @@ }); it('should highlight according to the language passed as argument in url', function() { - cy.visit(`${contentWithLanguageInfo}?language=${languageSelect}`); + cy.visit(`${contentWithLanguageInfo}&language=${languageSelect}`); checkLanguageHighlighting(languageSelect); }); diff --git a/cypress/integration/origin-visits.spec.js b/cypress/integration/origin-visits.spec.js --- a/cypress/integration/origin-visits.spec.js +++ b/cypress/integration/origin-visits.spec.js @@ -12,7 +12,9 @@ function checkTimeLink(element) { expect(element.text()).not.to.be.empty; - const timeStringLink = element.attr('href').split('visit/')[1].split('/')[0]; + const urlParams = new URLSearchParams(element.attr('href').split('?')[1]); + + const timeStringLink = urlParams.get('timestamp'); // time in link should be equal to that in text assert.deepEqual(getTime(timeStringLink), getTime(element.text())); diff --git a/cypress/integration/persistent-identifiers.spec.js b/cypress/integration/persistent-identifiers.spec.js --- a/cypress/integration/persistent-identifiers.spec.js +++ b/cypress/integration/persistent-identifiers.spec.js @@ -21,8 +21,8 @@ before(function() { origin = this.origin[1]; - url = this.Urls.browse_origin_content(origin.url, origin.content[0].path); - url = `${url}?release=${origin.release}#L${firstSelLine}-L${lastSelLine}`; + url = `${this.Urls.browse_origin_content(origin.url)}?path=${origin.content[0].path}`; + url = `${url}&release=${origin.release}#L${firstSelLine}-L${lastSelLine}`; originBadgeUrl = this.Urls.swh_badge('origin', origin.url); originBrowseUrl = this.Urls.browse_origin(origin.url); cy.visit(url).window().then(win => { 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 @@ -36,7 +36,64 @@ Origin directory """""""""""""""" -.. http:get:: /browse/origin/(origin_url)/directory/[(path)/] +.. http:get:: /browse/origin/(origin_url)/directory/ + + HTML view for browsing the content of a directory reachable from the root directory + (including itself) associated to the latest full visit of a software origin. + + 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 origin root directory. + A breadcrumb located in the top part of the view allows + to keep track of the paths navigated so far. + + The view also enables to easily switch between the origin branches + and releases through a dropdown menu. + + The origin branch (default to master) from which to retrieve the directory + content can also be specified by using the branch query parameter. + + :param string origin_url: the url of the origin (e.g. https://github.com/(user)/(repo)/) + :query string path: optional parameter used to specify the path of a directory + reachable from the origin root one + :query string branch: specify the origin branch name from which + to retrieve the root directory + :query string release: specify the origin release name from which + to retrieve the root directory + :query string revision: specify the origin revision, identified by the hexadecimal + representation of its **sha1_git** value, from which to retrieve the root directory + :query string timestamp: a date string (any format parsable by `dateutil.parser.parse`_) + or Unix timestamp to parse in order to find the closest visit. + :query int visit_id: specify a visit id to retrieve the directory from instead + of using the latest full visit by default + :statuscode 200: no error + :statuscode 404: requested origin can not be found in the archive + or the provided path does not exist from the origin root directory + + **Examples:** + + .. parsed-literal:: + + :swh_web_browse:`origin/https://github.com/torvalds/linux/directory/` + :swh_web_browse:`origin/https://github.com/torvalds/linux/directory/?path=net/ethernet` + :swh_web_browse:`origin/https://github.com/python/cpython/directory/` + :swh_web_browse:`origin/https://github.com/python/cpython/directory/?path=Python` + :swh_web_browse:`origin/https://github.com/python/cpython/directory/?branch=refs/heads/2.7` + :swh_web_browse:`origin/https://github.com/torvalds/linux/directory/?timestamp=1493926809` + :swh_web_browse:`origin/https://github.com/torvalds/linux/directory/?path=net/ethernet×tamp=2016-09-14T10:36:21` + :swh_web_browse:`origin/https://github.com/python/cpython/directory/?timestamp=1474620651` + :swh_web_browse:`origin/https://github.com/python/cpython/directory/?path=Python×tamp=2017-05-05` + :swh_web_browse:`origin/https://github.com/python/cpython/directory/?branch=refs/heads/2.7&/timestamp=2015-08` + + +.. http:get:: /browse/origin/(origin_url)/directory/(path)/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/origin/(origin_url)/directory/` instead. HTML view for browsing the content of a directory reachable from the root directory (including itself) associated to the latest full visit of a software origin. @@ -82,7 +139,11 @@ :swh_web_browse:`origin/https://github.com/python/cpython/directory/?branch=refs/heads/2.7` -.. http:get:: /browse/origin/(origin_url)/visit/(timestamp)/directory/[(path)/] +.. http:get:: /browse/origin/(origin_url)/visit/(timestamp)/directory/(path)/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/origin/(origin_url)/directory/` instead. HTML view for browsing the content of a directory reachable from the root directory (including itself) associated to a visit of a software @@ -136,7 +197,67 @@ Origin content """""""""""""" +.. http:get:: /browse/origin/(origin_url)/content/ + + HTML view that produces a display of a content + associated to the latest full visit of a software origin. + + If the content to display is textual, it will be highlighted client-side + if possible using highlightjs_. The procedure to perform that task is described + in :http:get:`/browse/content/[(algo_hash):](hash)/`. + + It is also possible to highlight specific lines of a textual + content (not in terms of syntax highlighting but to emphasize + some relevant content part) by either: + + * clicking on line numbers (holding shift to highlight a lines range) + + * using an url fragment in the form '#Ln' or '#Lm-Ln' + + The view displays a breadcrumb on top of the rendered + content in order to easily navigate up to the origin root directory. + + The view also enables to easily switch between the origin branches + and releases through a dropdown menu. + + The origin branch (default to master) from which to retrieve the content + can also be specified by using the branch query parameter. + + :param string origin_url: the url of the origin (e.g. https://github.com/(user)/(repo)/) + :query string path: path of a content reachable from the origin root directory + :query string branch: specify the origin branch name from which + to retrieve the content + :query string release: specify the origin release name from which + to retrieve the content + :query string revision: specify the origin revision, identified by the hexadecimal + representation of its **sha1_git** value, from which to retrieve the content + :query string timestamp: a date string (any format parsable by `dateutil.parser.parse`_) + or Unix timestamp to parse in order to find the closest visit. + :query int visit_id: specify a visit id to retrieve the content from instead + of using the latest full visit by default + :statuscode 200: no error + :statuscode 404: requested origin can not be found in the archive, + or the provided content path does not exist from the origin root directory + + **Examples:** + + .. parsed-literal:: + + :swh_web_browse:`origin/https://github.com/git/git/content/?path=git.c` + :swh_web_browse:`origin/https://github.com/mozilla/gecko-dev/content/?path=js/src/json.cpp` + :swh_web_browse:`origin/https://github.com/git/git/content/?path=git.c&branch=refs/heads/next` + :swh_web_browse:`origin/https://github.com/git/git/content/?path=git.c×tamp=1473933564` + :swh_web_browse:`origin/https://github.com/git/git/content/?path=git.c×tamp=2016-05-05T00:0:00+00:00` + :swh_web_browse:`origin/https://github.com/mozilla/gecko-dev/content?path=js/src/json.cpp×tamp=1490126182` + :swh_web_browse:`origin/https://github.com/mozilla/gecko-dev/content?path=js/src/json.cpp×tamp=2017-03-21#L904-L931` + :swh_web_browse:`origin/https://github.com/git/git/content/git.c/?branch=refs/heads/next×tamp=2017-09-15` + + .. http:get:: /browse/origin/(origin_url)/content/(path)/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/origin/(origin_url)/content/` instead. HTML view that produces a display of a content associated to the latest full visit of a software origin. @@ -186,6 +307,10 @@ :swh_web_browse:`origin/https://github.com/git/git/content/git.c/?branch=refs/heads/next` .. http:get:: /browse/origin/(origin_url)/visit/(timestamp)/content/(path)/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/origin/(origin_url)/content/` instead. HTML view that produces a display of a content associated to a visit of a software origin closest to a provided timestamp. @@ -286,6 +411,8 @@ to retrieve the commit log :query string revision: specify the origin revision, identified by the hexadecimal representation of its **sha1_git** value, from which to retrieve the commit log + :query string timestamp: a date string (any format parsable by `dateutil.parser.parse`_) + or Unix timestamp to parse in order to find the closest visit. :query int visit_id: specify a visit id to retrieve the history log from instead of using the latest visit by default :statuscode 200: no error @@ -298,9 +425,17 @@ :swh_web_browse:`origin/https://github.com/videolan/vlc/log/` :swh_web_browse:`origin/https://github.com/Kitware/CMake/log/` :swh_web_browse:`origin/https://github.com/Kitware/CMake/log/?branch=refs/heads/release` + :swh_web_browse:`origin/https://github.com/videolan/vlc/log/?visit=1459651262` + :swh_web_browse:`origin/https://github.com/Kitware/CMake/log/?timestamp=2016-04-01` + :swh_web_browse:`origin/https://github.com/Kitware/CMake/log/?branch=refs/heads/release×tamp=1438116814` + :swh_web_browse:`origin/https://github.com/Kitware/CMake/log/?branch=refs/heads/release×tamp=2017-05-05T03:14:23` .. http:get:: /browse/origin/(origin_url)/visit/(timestamp)/log/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/origin/(origin_url)/log/` instead. HTML view that produces a display of revisions history heading to the last revision found during a visit of a software origin closest @@ -333,11 +468,6 @@ :param string origin_url: the url of the origin (e.g. https://github.com/(user)/(repo)/) :param string timestamp: a date string (any format parsable by `dateutil.parser.parse`_) or Unix timestamp to parse in order to find the closest visit. - :query string revs_breadcrumb: used internally to store - the navigation breadcrumbs (i.e. the list of descendant revisions - visited so far). It must be a string in the form - "(rev_1)[/(rev_2)/.../(rev_n)]" where rev_i corresponds to a - revision **sha1_git**. :query int per_page: the number of log entries to display per page (default is 20, max is 50) :query string branch: specify the origin branch name from which @@ -379,6 +509,8 @@ That list of branches is paginated, each page displaying a maximum of 100 branches. :param string origin_url: the url of the origin (e.g. https://github.com/(user)/(repo)/) + :query string timestamp: a date string (any format parsable by `dateutil.parser.parse`_) + or Unix timestamp to parse in order to find the closest visit. :statuscode 200: no error :statuscode 404: requested origin can not be found in the archive @@ -388,8 +520,15 @@ :swh_web_browse:`origin/deb://Debian/packages/linux/branches/` :swh_web_browse:`origin/https://github.com/webpack/webpack/branches/` + :swh_web_browse:`origin/https://github.com/kripken/emscripten/branches/?timestamp=2017-05-05T12:02:03` + :swh_web_browse:`origin/deb://Debian/packages/apache2-mod-xforward/branches/?timestamp=2017-11-15T05:15:09` + .. http:get:: /browse/origin/(origin_url)/visit/(timestamp)/branches/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/origin/(origin_url)/branches/` instead. HTML view that produces a display of the list of branches found during a visit of a software origin closest to the provided timestamp. @@ -436,6 +575,8 @@ That list of releases is paginated, each page displaying a maximum of 100 releases. :param string origin_url: the url of the origin (e.g. https://github.com/(user)/(repo)/) + :query string timestamp: a date string (any format parsable by `dateutil.parser.parse`_) + or Unix timestamp to parse in order to find the closest visit. :statuscode 200: no error :statuscode 404: requested origin can not be found in the archive @@ -445,8 +586,15 @@ :swh_web_browse:`origin/https://github.com/git/git/releases/` :swh_web_browse:`origin/https://github.com/webpack/webpack/releases/` + :swh_web_browse:`origin/https://github.com/torvalds/linux/releases/?timestamp=2017-11-21T19:37:42` + :swh_web_browse:`origin/https://github.com/Kitware/CMake/releases/?timestamp=2016-09-23T14:06:35` + .. http:get:: /browse/origin/(origin_url)/visit/(timestamp)/releases/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/origin/(origin_url)/releases/` instead. HTML view that produces a display of the list of releases found during a visit of a software origin closest to the provided timestamp. @@ -474,5 +622,6 @@ :swh_web_browse:`origin/https://github.com/torvalds/linux/visit/2017-11-21T19:37:42/releases/` :swh_web_browse:`origin/https://github.com/Kitware/CMake/visit/2016-09-23T14:06:35/releases/` + .. _highlightjs: https://highlightjs.org/ .. _dateutil.parser.parse: http://dateutil.readthedocs.io/en/stable/parser.html 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 @@ -14,7 +14,7 @@ of a common one). Currently, that endpoint simply performs a redirection to - :http:get:`/browse/snapshot/(snapshot_id)/directory/[(path)/]` + :http:get:`/browse/snapshot/(snapshot_id)/directory/` in order to display the root directory associated to the default snapshot branch (usually master). @@ -35,14 +35,50 @@ Snapshot directory """""""""""""""""" -.. http:get:: /browse/snapshot/(snapshot_id)/directory/[(path)/] +.. http:get:: /browse/snapshot/(snapshot_id)/directory/ HTML view that displays the content of a directory reachable from a snapshot. The features offered by the view are similar to the one for browsing a directory in an origin context - (see :http:get:`/browse/origin/(origin_url)/directory/[(path)/]`). + (see :http:get:`/browse/origin/(origin_url)/directory/`). + + :param string snapshot_id: hexadecimal representation of the snapshot **sha1** identifier + :query string path: optional parameter used to specify the path of a directory + reachable from the snapshot root one + :query string branch: specify the snapshot branch name from which + to retrieve the root directory + :query string release: specify the snapshot release name from which + to retrieve the root directory + :query string revision: specify the snapshot revision, identified by the hexadecimal + representation of its **sha1_git** value, from which to retrieve the root directory + + :statuscode 200: no error + :statuscode 400: an invalid snapshot identifier has been provided + :statuscode 404: requested snapshot can not be found in the archive + + **Examples:** + + .. parsed-literal:: + + :swh_web_browse:`snapshot/baebc2109e4a2ec22a1129a3859647e191d04df4/directory/?path=drivers/gpu` + :swh_web_browse:`snapshot/673156c31a876c5b99b2fe3e89615529de9a3c44/directory/?path=src/opengl` + :swh_web_browse:`snapshot/673156c31a876c5b99b2fe3e89615529de9a3c44/directory/?release=v5.7.0` + + +.. http:get:: /browse/snapshot/(snapshot_id)/directory/(path)/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/snapshot/(snapshot_id)/directory/` instead. + + HTML view that displays the content of a directory reachable from + a snapshot. + + The features offered by the view are similar to the one for browsing + a directory in an origin context + (see :http:get:`/browse/origin/(origin_url)/directory/(path)/`). :param string snapshot_id: hexadecimal representation of the snapshot **sha1** identifier :param string path: optional parameter used to specify the path of a directory @@ -64,12 +100,49 @@ :swh_web_browse:`snapshot/baebc2109e4a2ec22a1129a3859647e191d04df4/directory/drivers/gpu/` :swh_web_browse:`snapshot/673156c31a876c5b99b2fe3e89615529de9a3c44/directory/src/opengl/` - :swh_web_browse:`snapshot/673156c31a876c5b99b2fe3e89615529de9a3c44/log/?release=v5.7.0` + :swh_web_browse:`snapshot/673156c31a876c5b99b2fe3e89615529de9a3c44/directory/?release=v5.7.0` + Snapshot content """""""""""""""" +.. http:get:: /browse/snapshot/(snapshot_id)/content/ + + HTML view that produces a display of a content reachable from + a snapshot. + + The features offered by the view are similar to the one for browsing + a content in an origin context + (see :http:get:`/browse/origin/(origin_url)/content/`). + + :param string snapshot_id: hexadecimal representation of the snapshot **sha1** identifier + :query string path: path of a content reachable from the snapshot root directory + :query string branch: specify the snapshot branch name from which + to retrieve the content + :query string release: specify the snapshot release name from which + to retrieve the content + :query string revision: specify the snapshot revision, identified by the hexadecimal + representation of its **sha1_git** value, from which to retrieve the content + + :statuscode 200: no error + :statuscode 400: an invalid snapshot identifier has been provided + :statuscode 404: requested snapshot can not be found in the archive, + or the provided content path does not exist from the origin root directory + + **Examples:** + + .. parsed-literal:: + + :swh_web_browse:`snapshot/baebc2109e4a2ec22a1129a3859647e191d04df4/content/?path=init/initramfs.c` + :swh_web_browse:`snapshot/673156c31a876c5b99b2fe3e89615529de9a3c44/content/?path=src/opengl/qglbuffer.h` + :swh_web_browse:`snapshot/673156c31a876c5b99b2fe3e89615529de9a3c44/content/?path=src/opengl/qglbuffer.h&?release=v5.0.0` + + .. http:get:: /browse/snapshot/(snapshot_id)/content/(path)/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/snapshot/(snapshot_id)/content/` instead. HTML view that produces a display of a content reachable from a snapshot. @@ -100,6 +173,7 @@ :swh_web_browse:`snapshot/673156c31a876c5b99b2fe3e89615529de9a3c44/content/src/opengl/qglbuffer.h/` :swh_web_browse:`snapshot/673156c31a876c5b99b2fe3e89615529de9a3c44/content/src/opengl/qglbuffer.h/?release=v5.0.0` + Snapshot history """""""""""""""" @@ -113,11 +187,6 @@ (see :http:get:`/browse/origin/(origin_url)/log/`). :param string snapshot_id: hexadecimal representation of the snapshot **sha1** identifier - :query string revs_breadcrumb: used internally to store - the navigation breadcrumbs (i.e. the list of descendant revisions - visited so far). It must be a string in the form - "(rev_1)[/(rev_2)/.../(rev_n)]" where rev_i corresponds to a - revision **sha1_git**. :query int per_page: the number of log entries to display per page (default is 20, max is 50) :query string branch: specify the snapshot branch name from which @@ -138,6 +207,7 @@ :swh_web_browse:`snapshot/a274b44111f777209556e94920b7e71cf5c305cd/log/` :swh_web_browse:`snapshot/9ca9e75279df5f4e3fee19bf5190ed672dcdfb33/log/?branch=refs/heads/emacs-unicode` + Snapshot branches """"""""""""""""" @@ -162,6 +232,7 @@ :swh_web_browse:`snapshot/03d7897352541e78ee7b13a580dc836778e8126a/branches/` :swh_web_browse:`snapshot/f37563b953327f8fd83e39af6ebb929ef85103d5/branches/` + Snapshot releases """"""""""""""""" 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 @@ -39,10 +39,10 @@ Wherever a revision context is expected in a path (i.e., a **/browse/revision/(sha1_git)/** path fragment) we can put in its stead a path fragment -of the form **/origin/(origin_url)/[/visit/(timestamp)/][?branch=(branch)]**. +of the form **/browse/origin/(origin_url)/?timestamp=(timestamp)&branch=(branch)**. Such a fragment is resolved, internally by the archive, to a revision **sha1_git** as follows: -- if **timestamp** is absent: look for the most recent crawl of origin +- if **timestamp** is not given as query parameter: look for the most recent crawl of origin identified by **origin_url** - if **timestamp** is given: look for the closest crawl of origin identified by **origin_url** from timestamp **timestamp** @@ -53,12 +53,9 @@ The already mentioned URLs for revision contexts can therefore be alternatively specified by users as: -* :http:get:`/browse/origin/(origin_url)/directory/[(path)/]` -* :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/directory/[(path)/]` -* :http:get:`/browse/origin/(origin_url)/content/(path)/` -* :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/content/(path)/` +* :http:get:`/browse/origin/(origin_url)/directory/` +* :http:get:`/browse/origin/(origin_url)/content/` * :http:get:`/browse/origin/(origin_url)/log/` -* :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/log/` Typing: 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 @@ -35,11 +35,10 @@ ) from swh.web.common import service, highlightjs -from swh.web.common.exc import handle_view_exception, NotFoundExc +from swh.web.common.exc import handle_view_exception, NotFoundExc, BadInputExc from swh.web.common.origin_visits import get_origin_visit from swh.web.common.typing import ( OriginInfo, - QueryParameters, SnapshotBranchInfo, SnapshotReleaseInfo, SnapshotContext, @@ -416,8 +415,9 @@ origin_info = None visit_info = None url_args = {} - query_params: QueryParameters = {} + query_params: Dict[str, Any] = {} origin_visits_url = None + if origin_url: origin_info = service.lookup_origin({"url": origin_url}) @@ -444,14 +444,16 @@ url_args = {"origin_url": origin_info["url"]} - query_params = {} if visit_id is not None: query_params["visit_id"] = visit_id origin_visits_url = reverse("browse-origin-visits", url_args=url_args) - if timestamp: - url_args["timestamp"] = format_utc_iso_date(timestamp, "%Y-%m-%dT%H:%M:%SZ") + if timestamp is not None: + query_params["timestamp"] = format_utc_iso_date( + timestamp, "%Y-%m-%dT%H:%M:%SZ" + ) + visit_url = reverse( "browse-origin-directory", url_args=url_args, query_params=query_params ) @@ -493,6 +495,9 @@ snapshot_total_size = sum(snapshot_sizes.values()) + if path is not None: + query_params["path"] = path + if snapshot_total_size and revision_id is not None: revision = service.lookup_revision(revision_id) root_directory = revision["directory"] @@ -547,30 +552,22 @@ ) for b in branches: - branch_url_args = dict(url_args) branch_query_params = dict(query_params) branch_query_params.pop("release", None) if b["name"] != b["revision"]: branch_query_params.pop("revision", None) branch_query_params["branch"] = b["name"] - if path: - branch_url_args["path"] = path b["url"] = reverse( - browse_view_name, url_args=branch_url_args, query_params=branch_query_params + browse_view_name, url_args=url_args, query_params=branch_query_params ) for r in releases: - release_url_args = dict(url_args) release_query_params = dict(query_params) release_query_params.pop("branch", None) release_query_params.pop("revision", None) release_query_params["release"] = r["name"] - if path: - release_url_args["path"] = path r["url"] = reverse( - browse_view_name, - url_args=release_url_args, - query_params=release_query_params, + browse_view_name, url_args=url_args, query_params=release_query_params, ) return SnapshotContext( @@ -598,7 +595,7 @@ def _build_breadcrumbs(snapshot_context: SnapshotContext, path: str): origin_info = snapshot_context["origin_info"] url_args = snapshot_context["url_args"] - query_params = snapshot_context["query_params"] + query_params = dict(snapshot_context["query_params"]) root_directory = snapshot_context["root_directory"] path_info = gen_path_info(path) @@ -610,6 +607,7 @@ breadcrumbs = [] if root_directory: + query_params.pop("path", None) breadcrumbs.append( { "name": root_directory[:7], @@ -619,13 +617,12 @@ } ) for pi in path_info: - bc_url_args = dict(url_args) - bc_url_args["path"] = pi["path"] + query_params["path"] = pi["path"] breadcrumbs.append( { "name": pi["name"], "url": reverse( - browse_view_name, url_args=bc_url_args, query_params=query_params + browse_view_name, url_args=url_args, query_params=query_params ), } ) @@ -669,7 +666,7 @@ origin_info = snapshot_context["origin_info"] visit_info = snapshot_context["visit_info"] url_args = snapshot_context["url_args"] - query_params = snapshot_context["query_params"] + query_params = dict(snapshot_context["query_params"]) revision_id = snapshot_context["revision_id"] snapshot_id = snapshot_context["snapshot_id"] @@ -686,10 +683,9 @@ if d["type"] == "rev": d["url"] = reverse("browse-revision", url_args={"sha1_git": d["target"]}) else: - bc_url_args = dict(url_args) - bc_url_args["path"] = path + d["name"] + query_params["path"] = path + d["name"] d["url"] = reverse( - browse_view_name, url_args=bc_url_args, query_params=query_params + browse_view_name, url_args=url_args, query_params=query_params ) sum_file_sizes = 0 @@ -702,10 +698,9 @@ browse_view_name = "browse-snapshot-content" for f in files: - bc_url_args = dict(url_args) - bc_url_args["path"] = path + f["name"] + query_params["path"] = path + f["name"] f["url"] = reverse( - browse_view_name, url_args=bc_url_args, query_params=query_params + browse_view_name, url_args=url_args, query_params=query_params ) if f["length"] is not None: sum_file_sizes += f["length"] @@ -841,6 +836,9 @@ """ try: + if path is None: + raise BadInputExc("The path of a content must be given as query parameter.") + snapshot_context = get_snapshot_context( snapshot_id=snapshot_id, origin_url=origin_url, diff --git a/swh/web/browse/utils.py b/swh/web/browse/utils.py --- a/swh/web/browse/utils.py +++ b/swh/web/browse/utils.py @@ -335,8 +335,8 @@ if snapshot_context and snapshot_context["origin_info"]: origin_info = snapshot_context["origin_info"] query_params = {"origin": origin_info["url"]} - if "timestamp" in snapshot_context["url_args"]: - query_params["timestamp"] = snapshot_context["url_args"]["timestamp"] + if "timestamp" in snapshot_context["query_params"]: + query_params["timestamp"] = snapshot_context["query_params"]["timestamp"] if "visit_id" in snapshot_context["query_params"]: query_params["visit_id"] = snapshot_context["query_params"]["visit_id"] elif snapshot_context: @@ -524,8 +524,8 @@ if snapshot_context and snapshot_context["origin_info"]: origin_info = snapshot_context["origin_info"] url_args = {"origin_url": origin_info["url"]} - if "timestamp" in snapshot_context["url_args"]: - url_args["timestamp"] = snapshot_context["url_args"]["timestamp"] + if "timestamp" in snapshot_context["query_params"]: + query_params["timestamp"] = snapshot_context["query_params"]["timestamp"] if "visit_id" in snapshot_context["query_params"]: query_params["visit_id"] = snapshot_context["query_params"]["visit_id"] revision_log_url = reverse( 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 @@ -21,33 +21,68 @@ from swh.web.common.utils import reverse, format_utc_iso_date, parse_timestamp +@browse_route( + r"origin/(?P.+)/directory/", view_name="browse-origin-directory", +) +def origin_directory_browse(request, origin_url): + """Django view for browsing the content of a directory associated + to an origin for a given visit. + + The URL that points to it is :http:get:`/browse/origin/(origin_url)/directory/` + """ + return browse_snapshot_directory( + request, + origin_url=origin_url, + timestamp=request.GET.get("timestamp"), + path=request.GET.get("path"), + ) + + @browse_route( r"origin/(?P.+)/visit/(?P.+)/directory/", r"origin/(?P.+)/visit/(?P.+)/directory/(?P.+)/", - r"origin/(?P.+)/directory/", r"origin/(?P.+)/directory/(?P.+)/", - view_name="browse-origin-directory", + view_name="browse-origin-directory-legacy", ) -def origin_directory_browse(request, origin_url, timestamp=None, path=None): +def origin_directory_browse_legacy(request, origin_url, timestamp=None, path=None): """Django view for browsing the content of a directory associated to an origin for a given visit. The url scheme that points to it is the following: - * :http:get:`/browse/origin/(origin_url)/directory/[(path)/]` - * :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/directory/[(path)/]` + * :http:get:`/browse/origin/(origin_url)/directory/(path)/` + * :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/directory/(path)/` """ return browse_snapshot_directory( request, origin_url=origin_url, timestamp=timestamp, path=path ) +@browse_route( + r"origin/(?P.+)/content/", view_name="browse-origin-content", +) +def origin_content_browse(request, origin_url): + """Django view that produces an HTML display of a content + associated to an origin for a given visit. + + The URL that points to it is :http:get:`/browse/origin/(origin_url)/content/` + + """ + return browse_snapshot_content( + request, + origin_url=origin_url, + timestamp=request.GET.get("timestamp"), + path=request.GET.get("path"), + selected_language=request.GET.get("language"), + ) + + @browse_route( r"origin/(?P.+)/visit/(?P.+)/content/(?P.+)/", r"origin/(?P.+)/content/(?P.+)/", - view_name="browse-origin-content", + view_name="browse-origin-content-legacy", ) -def origin_content_browse(request, origin_url, path=None, timestamp=None): +def origin_content_browse_legacy(request, origin_url, path=None, timestamp=None): """Django view that produces an HTML display of a content associated to an origin for a given visit. @@ -67,57 +102,89 @@ ) -PER_PAGE = 20 +@browse_route( + r"origin/(?P.+)/log/", view_name="browse-origin-log", +) +def origin_log_browse(request, origin_url): + """Django view that produces an HTML display of revisions history (aka + the commit log) associated to a software origin. + + The URL that points to it is :http:get:`/browse/origin/(origin_url)/log/` + """ + return browse_snapshot_log( + request, origin_url=origin_url, timestamp=request.GET.get("timestamp") + ) @browse_route( r"origin/(?P.+)/visit/(?P.+)/log/", - r"origin/(?P.+)/log/", - view_name="browse-origin-log", + view_name="browse-origin-log-legacy", ) -def origin_log_browse(request, origin_url, timestamp=None): +def origin_log_browse_legacy(request, origin_url, timestamp=None): """Django view that produces an HTML display of revisions history (aka the commit log) associated to a software origin. - The url scheme that points to it is the following: - - * :http:get:`/browse/origin/(origin_url)/log/` - * :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/log/` + The URL that points to it is + :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/log/` """ return browse_snapshot_log(request, origin_url=origin_url, timestamp=timestamp) @browse_route( - r"origin/(?P.+)/visit/(?P.+)/branches/", - r"origin/(?P.+)/branches/", - view_name="browse-origin-branches", + r"origin/(?P.+)/branches/", view_name="browse-origin-branches", ) -def origin_branches_browse(request, origin_url, timestamp=None): +def origin_branches_browse(request, origin_url): """Django view that produces an HTML display of the list of branches associated to an origin for a given visit. - The url scheme that points to it is the following: + The URL that points to it is :http:get:`/browse/origin/(origin_url)/branches/` + + """ + return browse_snapshot_branches( + request, origin_url=origin_url, timestamp=request.GET.get("timestamp") + ) - * :http:get:`/browse/origin/(origin_url)/branches/` - * :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/branches/` + +@browse_route( + r"origin/(?P.+)/visit/(?P.+)/branches/", + 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 + associated to an origin for a given visit. + + The URL that points to it is + :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/branches/` """ return browse_snapshot_branches(request, origin_url=origin_url, timestamp=timestamp) @browse_route( - r"origin/(?P.+)/visit/(?P.+)/releases/", - r"origin/(?P.+)/releases/", - view_name="browse-origin-releases", + r"origin/(?P.+)/releases/", view_name="browse-origin-releases", ) -def origin_releases_browse(request, origin_url, timestamp=None): +def origin_releases_browse(request, origin_url): """Django view that produces an HTML display of the list of releases associated to an origin for a given visit. - The url scheme that points to it is the following: + The URL that points to it is :http:get:`/browse/origin/(origin_url)/releases/` + + """ + return browse_snapshot_releases( + request, origin_url=origin_url, timestamp=request.GET.get("timestamp") + ) + + +@browse_route( + r"origin/(?P.+)/visit/(?P.+)/releases/", + view_name="browse-origin-releases-legacy", +) +def origin_releases_browse_legacy(request, origin_url, timestamp=None): + """Django view that produces an HTML display of the list of releases + associated to an origin for a given visit. - * :http:get:`/browse/origin/(origin_url)/releases/` - * :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/releases/` + The URL that points to it is + :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/releases/` """ return browse_snapshot_releases(request, origin_url=origin_url, timestamp=timestamp) @@ -141,7 +208,7 @@ for i, visit in enumerate(origin_visits): url_date = format_utc_iso_date(visit["date"], "%Y-%m-%dT%H:%M:%SZ") visit["formatted_date"] = format_utc_iso_date(visit["date"]) - query_params = {} + query_params = {"timestamp": url_date} if i < len(origin_visits) - 1: if visit["date"] == origin_visits[i + 1]["date"]: query_params = {"visit_id": visit["visit"]} @@ -153,7 +220,7 @@ visit["url"] = reverse( "browse-origin-directory", - url_args={"origin_url": origin_url, "timestamp": url_date}, + url_args={"origin_url": origin_url}, query_params=query_params, ) if not snapshot: @@ -184,6 +251,8 @@ snapshot for a given software origin. """ last_snapshot_url = reverse( - "browse-origin-directory", url_args={"origin_url": origin_url} + "browse-origin-directory", + url_args={"origin_url": origin_url}, + query_params=request.GET, ) return redirect(last_snapshot_url) 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 @@ -45,8 +45,8 @@ def _gen_content_url(revision, query_string, path, snapshot_context): if snapshot_context: url_args = snapshot_context["url_args"] - url_args["path"] = path query_params = snapshot_context["query_params"] + query_params["path"] = path query_params["revision"] = revision["id"] content_url = reverse( "browse-origin-content", url_args=url_args, query_params=query_params 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 @@ -38,16 +38,34 @@ @browse_route( r"snapshot/(?P[0-9a-f]+)/directory/", - r"snapshot/(?P[0-9a-f]+)/directory/(?P.+)/", view_name="browse-snapshot-directory", checksum_args=["snapshot_id"], ) -def snapshot_directory_browse(request, snapshot_id, path=None): +def snapshot_directory_browse(request, snapshot_id): """Django view for browsing the content of a directory collected in a snapshot. - The url that points to it is - :http:get:`/browse/snapshot/(snapshot_id)/directory/[(path)/]` + The URL that points to it is :http:get:`/browse/snapshot/(snapshot_id)/directory/` + """ + return browse_snapshot_directory( + request, + snapshot_id=snapshot_id, + path=request.GET.get("path"), + origin_url=request.GET.get("origin"), + ) + + +@browse_route( + r"snapshot/(?P[0-9a-f]+)/directory/(?P.+)/", + view_name="browse-snapshot-directory-legacy", + checksum_args=["snapshot_id"], +) +def snapshot_directory_browse_legacy(request, snapshot_id, path=None): + """Django view for browsing the content of a directory collected + in a snapshot. + + The URL that points to it is + :http:get:`/browse/snapshot/(snapshot_id)/directory/(path)/` """ origin_url = request.GET.get("origin_url", None) if not origin_url: @@ -58,20 +76,41 @@ @browse_route( - r"snapshot/(?P[0-9a-f]+)/content/(?P.+)/", + r"snapshot/(?P[0-9a-f]+)/content/", view_name="browse-snapshot-content", checksum_args=["snapshot_id"], ) -def snapshot_content_browse(request, snapshot_id, path): +def snapshot_content_browse(request, snapshot_id): + """Django view that produces an HTML display of a content + collected in a snapshot. + + The url that points to it is :http:get:`/browse/snapshot/(snapshot_id)/content/` + """ + return browse_snapshot_content( + request, + snapshot_id=snapshot_id, + path=request.GET.get("path"), + selected_language=request.GET.get("language"), + ) + + +@browse_route( + r"snapshot/(?P[0-9a-f]+)/content/(?P.+)/", + view_name="browse-snapshot-content-legacy", + checksum_args=["snapshot_id"], +) +def snapshot_content_browse_legacy(request, snapshot_id, path): """Django view that produces an HTML display of a content collected in a snapshot. The url that points to it is :http:get:`/browse/snapshot/(snapshot_id)/content/(path)/` """ - language = request.GET.get("language", None) return browse_snapshot_content( - request, snapshot_id=snapshot_id, path=path, selected_language=language + request, + snapshot_id=snapshot_id, + path=path, + selected_language=request.GET.get("language"), ) diff --git a/swh/web/templates/browse/help.html b/swh/web/templates/browse/help.html --- a/swh/web/templates/browse/help.html +++ b/swh/web/templates/browse/help.html @@ -153,8 +153,8 @@ Display a content from an origin: - - {% url 'browse-origin-content' origin_url='https://github.com/git/git' path='git.c' %} + + {% url 'browse-origin-content' origin_url='https://github.com/git/git'%}?path=git.c
  • @@ -162,8 +162,8 @@ directory from an origin: - - {% url 'browse-origin-directory' origin_url='https://github.com/torvalds/linux' path='net/ethernet' %} + + {% url 'browse-origin-directory' origin_url='https://github.com/torvalds/linux'%}?path=net/ethernet
  • 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 @@ -91,6 +91,9 @@ url_args = {"snapshot_id": snapshot} + query_params = dict(kwargs) + query_params.pop("snapshot_id") + snapshot_context = get_snapshot_context(**kwargs, browse_context=browse_context) branches, releases = get_snapshot_content(snapshot) @@ -103,14 +106,14 @@ root_directory = branch["directory"] branch["url"] = reverse( f"browse-snapshot-{browse_context}", - url_args=kwargs, - query_params={"branch": branch["name"]}, + url_args=url_args, + query_params={"branch": branch["name"], **query_params}, ) for release in releases: release["url"] = reverse( f"browse-snapshot-{browse_context}", - url_args=kwargs, - query_params={"release": release["name"]}, + url_args=url_args, + query_params={"release": release["name"], **query_params}, ) branches_url = reverse("browse-snapshot-branches", url_args=url_args) @@ -128,7 +131,7 @@ origin_visits_url=None, release=None, release_id=None, - query_params={}, + query_params=query_params, releases=releases, releases_url=releases_url, revision_id=revision_id, @@ -174,11 +177,12 @@ snapshot_context = get_snapshot_context(**kwargs, browse_context=browse_context) url_args = dict(kwargs) + url_args.pop("path", None) + url_args.pop("timestamp", None) url_args.pop("visit_id", None) - query_params = {} - if "visit_id" in kwargs: - query_params["visit_id"] = kwargs["visit_id"] + query_params = dict(kwargs) + query_params.pop("origin_url") branches, releases = get_snapshot_content(snapshot) releases = list(reversed(releases)) @@ -200,7 +204,7 @@ query_params={"release": release["name"], **query_params}, ) - url_args.pop("path", None) + query_params.pop("path", None) branches_url = reverse( "browse-origin-branches", url_args=url_args, query_params=query_params @@ -220,6 +224,9 @@ ) visit_info["formatted_date"] = format_utc_iso_date(visit_info["date"]) + if "path" in kwargs: + query_params["path"] = kwargs["path"] + expected = SnapshotContext( branch="HEAD", branches=branches, @@ -257,9 +264,14 @@ **kwargs, browse_context=browse_context, branch_name=branch["name"] ) - query_params = {} - if "visit_id" in kwargs: - query_params["visit_id"] = kwargs["visit_id"] + url_args = dict(kwargs) + url_args.pop("path", None) + url_args.pop("timestamp", None) + url_args.pop("visit_id", None) + + query_params = dict(kwargs) + query_params.pop("origin_url", None) + query_params.pop("snapshot_id", None) expected_branch = dict(base_expected_context) expected_branch["branch"] = branch["name"] @@ -304,7 +316,7 @@ revision_browse_url = reverse( view_name, - url_args=kwargs, + url_args=url_args, query_params={"revision": revision["id"], **query_params}, ) 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 @@ -63,7 +63,8 @@ vdate = format_utc_iso_date(v["date"], "%Y-%m-%dT%H:%M:%SZ") browse_dir_url = reverse( "browse-origin-directory", - url_args={"origin_url": origin["url"], "timestamp": vdate}, + url_args={"origin_url": origin["url"]}, + query_params={"timestamp": vdate}, ) assert_contains(resp, browse_dir_url) @@ -495,7 +496,8 @@ def test_browse_origin_directory_not_found(client, origin): url = reverse( "browse-origin-directory", - url_args={"origin_url": origin["url"], "path": "/invalid/dir/path/"}, + url_args={"origin_url": origin["url"]}, + query_params={"path": "/invalid/dir/path/"}, ) resp = client.get(url) assert resp.status_code == 404 @@ -510,7 +512,9 @@ ) mock_get_origin_visits.return_value = [] url = reverse( - "browse-origin-content", url_args={"origin_url": origin["url"], "path": "foo"} + "browse-origin-content", + url_args={"origin_url": origin["url"]}, + query_params={"path": "foo"}, ) resp = client.get(url) assert resp.status_code == 404 @@ -528,8 +532,8 @@ url = reverse( "browse-origin-content", - url_args={"origin_url": origin["url"], "path": "foo"}, - query_params={"visit_id": 2}, + url_args={"origin_url": origin["url"]}, + query_params={"path": "foo", "visit_id": 2}, ) resp = client.get(url) assert resp.status_code == 404 @@ -551,7 +555,9 @@ "release": 0, } url = reverse( - "browse-origin-content", url_args={"origin_url": origin["url"], "path": "baz"} + "browse-origin-content", + url_args={"origin_url": origin["url"]}, + query_params={"path": "baz"}, ) resp = client.get(url) assert resp.status_code == 200 @@ -566,7 +572,8 @@ def test_browse_origin_content_not_found(client, origin): url = reverse( "browse-origin-content", - url_args={"origin_url": origin["url"], "path": "/invalid/file/path"}, + url_args={"origin_url": origin["url"]}, + query_params={"path": "/invalid/file/path"}, ) resp = client.get(url) assert resp.status_code == 404 @@ -687,6 +694,18 @@ ) +@given(origin()) +def test_origin_content_no_path(client, origin): + url = reverse("browse-origin-content", url_args={"origin_url": origin["url"]}) + + resp = client.get(url) + + assert resp.status_code == 400 + assert_contains( + resp, "The path of a content must be given as query parameter.", status_code=400 + ) + + def _origin_content_view_test_helper( client, origin_info, @@ -700,15 +719,15 @@ ): content_path = "/".join(content["path"].split("/")[1:]) - url_args = {"origin_url": origin_info["url"], "path": content_path} + url_args = {"origin_url": origin_info["url"]} if not visit_id: visit_id = origin_visits[-1]["visit"] - query_params = {} + query_params = {"path": content_path} if timestamp: - url_args["timestamp"] = timestamp + query_params["timestamp"] = timestamp if visit_id: query_params["visit_id"] = visit_id @@ -732,10 +751,10 @@ path_info = gen_path_info(path) - del url_args["path"] + del query_params["path"] if timestamp: - url_args["timestamp"] = format_utc_iso_date( + query_params["timestamp"] = format_utc_iso_date( parse_timestamp(timestamp).isoformat(), "%Y-%m-%dT%H:%M:%SZ" ) @@ -748,7 +767,7 @@ assert_contains(resp, '%s' % (root_dir_url, root_dir_sha1[:7])) for p in path_info: - url_args["path"] = p["path"] + query_params["path"] = p["path"] dir_url = reverse( "browse-origin-directory", url_args=url_args, query_params=query_params ) @@ -765,8 +784,8 @@ ) assert_contains(resp, url_raw) - if "args" in url_args: - del url_args["path"] + if "path" in query_params: + del query_params["path"] origin_branches_url = reverse( "browse-origin-branches", url_args=url_args, query_params=query_params @@ -774,7 +793,8 @@ assert_contains( resp, - 'Branches (%s)' % (origin_branches_url, len(origin_branches)), + 'Branches (%s)' + % (escape(origin_branches_url), len(origin_branches)), ) origin_releases_url = reverse( @@ -783,12 +803,13 @@ assert_contains( resp, - 'Releases (%s)' % (origin_releases_url, len(origin_releases)), + 'Releases (%s)' + % (escape(origin_releases_url), len(origin_releases)), ) assert_contains(resp, '
  • ', count=len(origin_branches)) - url_args["path"] = content_path + query_params["path"] = content_path for branch in origin_branches: query_params["branch"] = branch["name"] @@ -846,12 +867,12 @@ query_params = {} if timestamp: - url_args["timestamp"] = timestamp + query_params["timestamp"] = timestamp else: query_params["visit_id"] = visit_id if path: - url_args["path"] = path + query_params["path"] = path url = reverse( "browse-origin-directory", url_args=url_args, query_params=query_params @@ -869,7 +890,7 @@ assert_contains(resp, '', count=len(files)) if timestamp: - url_args["timestamp"] = format_utc_iso_date( + query_params["timestamp"] = format_utc_iso_date( parse_timestamp(timestamp).isoformat(), "%Y-%m-%dT%H:%M:%SZ" ) @@ -880,12 +901,9 @@ dir_path = d["name"] if path: dir_path = "%s/%s" % (path, d["name"]) - dir_url_args = dict(url_args) - dir_url_args["path"] = dir_path + query_params["path"] = dir_path dir_url = reverse( - "browse-origin-directory", - url_args=dir_url_args, - query_params=query_params, + "browse-origin-directory", url_args=url_args, query_params=query_params, ) assert_contains(resp, dir_url) @@ -893,15 +911,14 @@ file_path = f["name"] if path: file_path = "%s/%s" % (path, f["name"]) - file_url_args = dict(url_args) - file_url_args["path"] = file_path + query_params["path"] = file_path file_url = reverse( - "browse-origin-content", url_args=file_url_args, query_params=query_params + "browse-origin-content", url_args=url_args, query_params=query_params ) assert_contains(resp, file_url) - if "path" in url_args: - del url_args["path"] + if "path" in query_params: + del query_params["path"] root_dir_branch_url = reverse( "browse-origin-directory", url_args=url_args, query_params=query_params @@ -936,7 +953,7 @@ ) if path: - url_args["path"] = path + query_params["path"] = path assert_contains(resp, '
  • ', count=len(origin_branches))