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 @@ -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 @@ -18,7 +18,7 @@ describe('Code highlighting tests', function() { before(function() { origin = this.origin[0]; - url = `${this.Urls.browse_origin_content(origin.url)}?path=${origin.content[0].path}`; + url = `${this.Urls.browse_origin_content()}?origin_url=${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 @@ -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 @@ -11,7 +11,7 @@ describe('Test File Rendering', function() { before(function() { origin = this.origin[0]; - url = `${this.Urls.browse_origin_content(origin.url)}?path=${origin.content[0].path}`; + url = `${this.Urls.browse_origin_content()}?origin_url=${origin.url}&path=${origin.content[0].path}`; }); beforeEach(function() { @@ -43,7 +43,7 @@ }); it('should have links to all ancestor directories', function() { - const rootDirUrl = this.Urls.browse_origin_directory(origin.url); + const rootDirUrl = `${this.Urls.browse_origin_directory()}?origin_url=${origin.url}`; cy.get(`a[href='${rootDirUrl}']`) .should('be.visible'); @@ -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)}?path=${subDirPath}`; + const subDirUrl = `${this.Urls.browse_origin_directory()}?origin_url=${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 @@ -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 @@ -17,7 +17,7 @@ before(function() { origin = this.origin[0]; - url = this.Urls.browse_origin_directory(origin.url); + url = `${this.Urls.browse_origin_directory()}?origin_url=${origin.url}`; for (let entry of origin.dirContent) { if (entry.type === 'file') { @@ -67,7 +67,7 @@ .click(); cy.url() - .should('include', `${url}?path=${dirs[0]['name']}`); + .should('include', `${url}&path=${dirs[0]['name']}`); cy.get('.swh-directory-table') .should('be.visible'); diff --git a/cypress/integration/errors.spec.js b/cypress/integration/errors.spec.js --- a/cypress/integration/errors.spec.js +++ b/cypress/integration/errors.spec.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 @@ -40,7 +40,7 @@ context('For unarchived repositories', function() { it('should display NotFoundExc for unarchived repo', function() { - const url = this.Urls.browse_origin_directory(this.unarchivedRepo.url); + const url = `${this.Urls.browse_origin_directory()}?origin_url=${this.unarchivedRepo.url}`; urlShouldShowError(url, { code: '404', @@ -88,13 +88,12 @@ context('For archived repositories', function() { before(function() { - const url = this.Urls.browse_origin_directory(origin.url); + const url = `${this.Urls.browse_origin_directory()}?origin_url=${origin.url}`; cy.visit(url); }); it('should display NotFoundExc for invalid directory from archived repo', function() { - const rootDir = this.Urls.browse_origin_directory(origin.url); - const subDir = rootDir + origin.invalidSubDir; + const subDir = `${this.Urls.browse_origin_directory()}?origin_url=${origin.url}&path=${origin.invalidSubDir}`; urlShouldShowError(subDir, { code: '404', 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 @@ -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 @@ -17,7 +17,7 @@ describe('Test Content Language Select', function() { before(function() { origin = this.origin[0]; - contentWithLanguageInfo = `${this.Urls.browse_origin_content(origin.url)}?path=${origin.content[1].path}`; + contentWithLanguageInfo = `${this.Urls.browse_origin_content()}?origin_url=${origin.url}&path=${origin.content[1].path}`; contentWithoutLanguageInfo = this.Urls.browse_content(`sha1_git:${origin.content[1].sha1git}`); }); 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 @@ -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 @@ -40,7 +40,7 @@ }); beforeEach(function() { - cy.visit(this.Urls.browse_origin_visits(origin.url)); + cy.visit(`${this.Urls.browse_origin_visits()}?origin_url=${origin.url}`); }); it('should display first full visit time', function() { 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 @@ -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 @@ -21,10 +21,10 @@ before(function() { origin = this.origin[1]; - url = `${this.Urls.browse_origin_content(origin.url)}?path=${origin.content[0].path}`; + url = `${this.Urls.browse_origin_content()}?origin_url=${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); + originBrowseUrl = `${this.Urls.browse_origin()}?origin_url=${origin.url}`; cy.visit(url).window().then(win => { urlPrefix = `${win.location.protocol}//${win.location.hostname}`; if (win.location.port) { 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 @@ -14,7 +14,32 @@ Origin visits """"""""""""" +.. http:get:: /browse/origin/visits/ + + HTML view that displays visits reporting for a software origin identified by + its type and url. + + :query string origin_url: mandatory parameter providing the url of the origin + (e.g. https://github.com/(user)/(repo)) + :statuscode 200: no error + :statuscode 400: no origin url has been provided as parameter + :statuscode 404: requested origin can not be found in the archive + + **Examples:** + + .. parsed-literal:: + + :swh_web_browse:`origin/visits/?origin_url=https://github.com/torvalds/linux` + :swh_web_browse:`origin/visits/?origin_url=https://github.com/python/cpython` + :swh_web_browse:`origin/visits/?origin_url=deb://Debian-Security/packages/mediawiki` + :swh_web_browse:`origin/visits/?origin_url=https://gitorious.org/qt/qtbase.git` + + .. http:get:: /browse/origin/(origin_url)/visits/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/origin/visits/` instead. HTML view that displays a visits reporting for a software origin identified by its type and url. @@ -36,7 +61,7 @@ Origin directory """""""""""""""" -.. http:get:: /browse/origin/(origin_url)/directory/ +.. http:get:: /browse/origin/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. @@ -53,10 +78,11 @@ 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 + The origin branch (default to HEAD) 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 origin_url: mandatory parameter providing 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 @@ -70,6 +96,7 @@ :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 400: no origin url has been provided as parameter :statuscode 404: requested origin can not be found in the archive or the provided path does not exist from the origin root directory @@ -77,23 +104,23 @@ .. 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` + :swh_web_browse:`origin/directory/?origin_url=https://github.com/torvalds/linux` + :swh_web_browse:`origin/directory/?origin_url=https://github.com/torvalds/linux&path=net/ethernet` + :swh_web_browse:`origin/directory/?origin_url=https://github.com/python/cpython` + :swh_web_browse:`origin/directory/?origin_url=https://github.com/python/cpython&path=Python` + :swh_web_browse:`origin/directory/?origin_url=https://github.com/python/cpython&branch=refs/heads/2.7` + :swh_web_browse:`origin/directory/?origin_url=https://github.com/torvalds/linux×tamp=1493926809` + :swh_web_browse:`origin/directory/?origin_url=https://github.com/torvalds/linux&path=net/ethernet×tamp=2016-09-14T10:36:21Z` + :swh_web_browse:`origin/directory/?origin_url=https://github.com/python/cpython×tamp=1474620651` + :swh_web_browse:`origin/directory/?origin_url=https://github.com/python/cpython&path=Python×tamp=2017-05-05` + :swh_web_browse:`origin/directory/?origin_url=https://github.com/python/cpython&branch=refs/heads/2.7×tamp=2015-08` -.. http:get:: /browse/origin/(origin_url)/directory/(path)/ +.. http:get:: /browse/origin/(origin_url)/directory/[(path)/] :deprecated: .. warning:: - That endpoint is deprecated, use :http:get:`/browse/origin/(origin_url)/directory/` instead. + That endpoint is deprecated, use :http:get:`/browse/origin/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. @@ -110,7 +137,7 @@ 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 + The origin branch (default to HEAD) 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)/) @@ -139,11 +166,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. + That endpoint is deprecated, use :http:get:`/browse/origin/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 @@ -161,7 +188,7 @@ 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 + The origin branch (default to HEAD) 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)/) @@ -188,7 +215,7 @@ .. parsed-literal:: :swh_web_browse:`origin/https://github.com/torvalds/linux/visit/1493926809/directory/` - :swh_web_browse:`origin/https://github.com/torvalds/linux/visit/2016-09-14T10:36:21/directory/net/ethernet/` + :swh_web_browse:`origin/https://github.com/torvalds/linux/visit/2016-09-14T10:36:21Z/directory/net/ethernet/` :swh_web_browse:`origin/https://github.com/python/cpython/visit/1474620651/directory/` :swh_web_browse:`origin/https://github.com/python/cpython/visit/2017-05-05/directory/Python/` :swh_web_browse:`origin/https://github.com/python/cpython/visit/2015-08/directory/?branch=refs/heads/2.7` @@ -197,7 +224,69 @@ Origin content """""""""""""" +.. http:get:: /browse/origin/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 HEAD) from which to retrieve the content + can also be specified by using the branch query parameter. + + :query string origin_url: mandatory parameter providing 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 400: no origin url has been provided as parameter + :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/content/?origin_url=https://github.com/git/git?path=git.c` + :swh_web_browse:`origin/content/?origin_url=https://github.com/mozilla/gecko-dev&path=js/src/json.cpp` + :swh_web_browse:`origin/content/?origin_url=https://github.com/git/git?path=git.c&branch=refs/heads/next` + :swh_web_browse:`origin/content/?origin_url=https://github.com/git/git&path=git.c×tamp=1473933564` + :swh_web_browse:`origin/content/?origin_url=https://github.com/git/git&path=git.c×tamp=2016-05-05T00:0:00+00:00Z` + :swh_web_browse:`origin/content/?origin_url=https://github.com/mozilla/gecko-dev&path=js/src/json.cpp×tamp=1490126182` + :swh_web_browse:`origin/content/?origin_url=https://github.com/mozilla/gecko-dev&path=js/src/json.cpp×tamp=2017-03-21#L904-L931` + :swh_web_browse:`origin/content/?origin_url=https://github.com/git/git&path=git.c&branch=refs/heads/next×tamp=2017-09-15` + + .. http:get:: /browse/origin/(origin_url)/content/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/origin/content/` instead. HTML view that produces a display of a content associated to the latest full visit of a software origin. @@ -220,7 +309,7 @@ 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 + The origin branch (default to HEAD) 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)/) @@ -236,6 +325,7 @@ :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 400: no origin url has been provided as parameter :statuscode 404: requested origin can not be found in the archive, or the provided content path does not exist from the origin root directory @@ -247,7 +337,7 @@ :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/git/git/content/?path=git.c×tamp=2016-05-05T00:0:00+00:00Z` :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` @@ -257,7 +347,7 @@ :deprecated: .. warning:: - That endpoint is deprecated, use :http:get:`/browse/origin/(origin_url)/content/` instead. + That endpoint is deprecated, use :http:get:`/browse/origin/content/` instead. HTML view that produces a display of a content associated to the latest full visit of a software origin. @@ -280,7 +370,7 @@ 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 + The origin branch (default to HEAD) 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)/) @@ -310,7 +400,7 @@ :deprecated: .. warning:: - That endpoint is deprecated, use :http:get:`/browse/origin/(origin_url)/content/` instead. + That endpoint is deprecated, use :http:get:`/browse/origin/content/` instead. HTML view that produces a display of a content associated to a visit of a software origin closest to a provided timestamp. @@ -334,7 +424,7 @@ 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 + The origin branch (default to HEAD) 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)/) @@ -359,7 +449,7 @@ .. parsed-literal:: :swh_web_browse:`origin/https://github.com/git/git/visit/1473933564/content/git.c/` - :swh_web_browse:`origin/https://github.com/git/git/visit/2016-05-05T00:0:00+00:00/content/git.c/` + :swh_web_browse:`origin/https://github.com/git/git/visit/2016-05-05T00:0:00+00:00Z/content/git.c/` :swh_web_browse:`origin/https://github.com/mozilla/gecko-dev/visit/1490126182/content/js/src/json.cpp/` :swh_web_browse:`origin/https://github.com/mozilla/gecko-dev/visit/2017-03-21/content/js/src/json.cpp/#L904-L931` :swh_web_browse:`origin/https://github.com/git/git/visit/2017-09-15/content/git.c/?branch=refs/heads/next` @@ -368,7 +458,76 @@ Origin history """""""""""""" +.. http:get:: /browse/origin/log/ + + HTML view that produces a display of revisions history heading + to the last revision found during the latest visit of a software origin. + In other words, it shows the commit log associated to the latest + full visit of a software origin. + + The following data are displayed for each log entry: + + * link to browse the associated revision in the origin context + * author of the revision + * date of the revision + * message associated the revision + * commit date of the revision + + By default, the revisions are ordered in reverse chronological order of + their commit date. + + N log entries are displayed per page (default is 100). In order to navigate + in a large history, two buttons are present at the bottom of the view: + + * **Newer**: fetch and display if available the N more recent log entries + than the ones currently displayed + * **Older**: fetch and display if available the N older log entries + than the ones currently displayed + + The view also enables to easily switch between the origin branches + and releases through a dropdown menu. + + The origin branch (default to HEAD) from which to retrieve the content + can also be specified by using the branch query parameter. + + :query string origin_url: mandatory parameter providing the url of the origin + (e.g. https://github.com/(user)/(repo)) + :query int per_page: the number of log entries to display per page + :query int offset: the number of revisions to skip before returning those to display + :query str revs_ordering: specify the revisions ordering, possible values are ``committer_date``, + ``dfs``, ``dfs_post`` and ``bfs`` + :query string branch: specify the origin branch name from which + to retrieve the commit log + :query string release: specify the origin release name from which + 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 + :statuscode 400: no origin url has been provided as parameter + :statuscode 404: requested origin can not be found in the archive + + **Examples:** + + .. parsed-literal:: + + :swh_web_browse:`origin/log/?origin_url=https://github.com/videolan/vlc` + :swh_web_browse:`origin/log/?origin_url=https://github.com/Kitware/CMake` + :swh_web_browse:`origin/log/?origin_url=https://github.com/Kitware/CMake&branch=refs/heads/release` + :swh_web_browse:`origin/log/?origin_url=https://github.com/videolan/vlc&visit=1459651262` + :swh_web_browse:`origin/log/?origin_url=https://github.com/Kitware/CMake×tamp=2016-04-01` + :swh_web_browse:`origin/log/?origin_url=https://github.com/Kitware/CMake&branch=refs/heads/release×tamp=1438116814` + :swh_web_browse:`origin/log/?origin_url=https://github.com/Kitware/CMake&branch=refs/heads/release×tamp=2017-05-05T03:14:23Z` + + .. http:get:: /browse/origin/(origin_url)/log/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/origin/log/` instead. HTML view that produces a display of revisions history heading to the last revision found during the latest visit of a software origin. @@ -397,10 +556,11 @@ 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 + The origin branch (default to HEAD) 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 origin_url: mandatory parameter providing the url of the origin + (e.g. https://github.com/(user)/(repo)) :query int per_page: the number of log entries to display per page :query int offset: the number of revisions to skip before returning those to display :query str revs_ordering: specify the revisions ordering, possible values are ``committer_date``, @@ -428,14 +588,14 @@ :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` + :swh_web_browse:`origin/https://github.com/Kitware/CMake/log/?branch=refs/heads/release×tamp=2017-05-05T03:14:23Z` .. http:get:: /browse/origin/(origin_url)/visit/(timestamp)/log/ :deprecated: .. warning:: - That endpoint is deprecated, use :http:get:`/browse/origin/(origin_url)/log/` instead. + That endpoint is deprecated, use :http:get:`/browse/origin/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 @@ -462,7 +622,7 @@ 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 + The origin branch (default to HEAD) 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)/) @@ -488,12 +648,49 @@ :swh_web_browse:`origin/https://github.com/videolan/vlc/visit/1459651262/log/` :swh_web_browse:`origin/https://github.com/Kitware/CMake/visit/2016-04-01/log/` :swh_web_browse:`origin/https://github.com/Kitware/CMake/visit/1438116814/log/?branch=refs/heads/release` - :swh_web_browse:`origin/https://github.com/Kitware/CMake/visit/2017-05-05T03:14:23/log/?branch=refs/heads/release` + :swh_web_browse:`origin/https://github.com/Kitware/CMake/visit/2017-05-05T03:14:23Z/log/?branch=refs/heads/release` Origin branches """"""""""""""" +.. http:get:: /browse/origin/branches/ + + HTML view that produces a display of the list of branches + found during the latest full visit of a software origin. + + The following data are displayed for each branch: + + * its name + * a link to browse the associated directory + * a link to browse the associated revision + * last commit message + * last commit date + + That list of branches is paginated, each page displaying a maximum of 100 branches. + + :query string origin_url: mandatory parameter providing 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 400: no origin url has been provided as parameter + :statuscode 404: requested origin can not be found in the archive + + **Examples:** + + .. parsed-literal:: + + :swh_web_browse:`origin/branches/?origin_url=deb://Debian/packages/linux` + :swh_web_browse:`origin/branches/?origin_url=https://github.com/webpack/webpack` + :swh_web_browse:`origin/branches/?origin_url=https://github.com/kripken/emscripten×tamp=2017-05-05T12:02:03Z` + :swh_web_browse:`origin/branches/?origin_url=deb://Debian/packages/apache2-mod-xforward×tamp=2017-11-15T05:15:09Z` + + .. http:get:: /browse/origin/(origin_url)/branches/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/origin/branches/` instead. HTML view that produces a display of the list of branches found during the latest full visit of a software origin. @@ -520,7 +717,7 @@ :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/https://github.com/kripken/emscripten/branches/?timestamp=2017-05-05T12:02:03Z` :swh_web_browse:`origin/deb://Debian/packages/apache2-mod-xforward/branches/?timestamp=2017-11-15T05:15:09` @@ -528,7 +725,7 @@ :deprecated: .. warning:: - That endpoint is deprecated, use :http:get:`/browse/origin/(origin_url)/branches/` instead. + That endpoint is deprecated, use :http:get:`/browse/origin/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. @@ -553,13 +750,50 @@ .. parsed-literal:: - :swh_web_browse:`origin/https://github.com/kripken/emscripten/visit/2017-05-05T12:02:03/branches/` - :swh_web_browse:`origin/deb://Debian/packages/apache2-mod-xforward/visit/2017-11-15T05:15:09/branches/` + :swh_web_browse:`origin/https://github.com/kripken/emscripten/visit/2017-05-05T12:02:03Z/branches/` + :swh_web_browse:`origin/deb://Debian/packages/apache2-mod-xforward/visit/2017-11-15T05:15:09Z/branches/` Origin releases """"""""""""""" +.. http:get:: /browse/origin/releases/ + + HTML view that produces a display of the list of releases + found during the latest full visit of a software origin. + + The following data are displayed for each release: + + * its name + * a link to browse the release details + * its target type (revision, directory, content or release) + * its associated message + * its date + + That list of releases is paginated, each page displaying a maximum of 100 releases. + + :query string origin_url: mandatory parameter providing 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 400: no origin url has been provided as parameter + :statuscode 404: requested origin can not be found in the archive + + **Examples:** + + .. parsed-literal:: + + :swh_web_browse:`origin/releases/?origin_url=https://github.com/git/git` + :swh_web_browse:`origin/releases/?origin_url=https://github.com/webpack/webpack` + :swh_web_browse:`origin/releases/?origin_url=https://github.com/torvalds/linux×tamp=2017-11-21T19:37:42Z` + :swh_web_browse:`origin/releases/?origin_url=https://github.com/Kitware/CMake×tamp=2016-09-23T14:06:35Z` + + .. http:get:: /browse/origin/(origin_url)/releases/ + :deprecated: + + .. warning:: + That endpoint is deprecated, use :http:get:`/browse/origin/releases/` instead. HTML view that produces a display of the list of releases found during the latest full visit of a software origin. @@ -586,15 +820,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` + :swh_web_browse:`origin/https://github.com/torvalds/linux/releases/?timestamp=2017-11-21T19:37:42Z` + :swh_web_browse:`origin/https://github.com/Kitware/CMake/releases/?timestamp=2016-09-23T14:06:35Z` .. http:get:: /browse/origin/(origin_url)/visit/(timestamp)/releases/ :deprecated: .. warning:: - That endpoint is deprecated, use :http:get:`/browse/origin/(origin_url)/releases/` instead. + That endpoint is deprecated, use :http:get:`/browse/origin/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. @@ -619,8 +853,8 @@ .. parsed-literal:: - :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/` + :swh_web_browse:`origin/https://github.com/torvalds/linux/visit/2017-11-21T19:37:42Z/releases/` + :swh_web_browse:`origin/https://github.com/Kitware/CMake/visit/2016-09-23T14:06:35Z/releases/` .. _highlightjs: https://highlightjs.org/ 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 @@ -42,7 +42,7 @@ 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/`). + (see :http:get:`/browse/origin/(origin_url)/directory/[(path)/]`). :param string snapshot_id: hexadecimal representation of the snapshot **sha1** identifier :query string path: optional parameter used to specify the path of a directory @@ -78,7 +78,7 @@ 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/[(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 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,7 +39,7 @@ 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 **/browse/origin/(origin_url)/?timestamp=(timestamp)&branch=(branch)**. +of the form **/browse/origin/?origin_url=(origin_url)×tamp=(timestamp)&branch=(branch)**. Such a fragment is resolved, internally by the archive, to a revision **sha1_git** as follows: - if **timestamp** is not given as query parameter: look for the most recent crawl of origin @@ -53,9 +53,9 @@ The already mentioned URLs for revision contexts can therefore be alternatively specified by users as: -* :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/directory/` +* :http:get:`/browse/origin/content/` +* :http:get:`/browse/origin/log/` Typing: diff --git a/swh/web/assets/src/bundles/admin/origin-save.js b/swh/web/assets/src/bundles/admin/origin-save.js --- a/swh/web/assets/src/bundles/admin/origin-save.js +++ b/swh/web/assets/src/bundles/admin/origin-save.js @@ -1,5 +1,5 @@ /** - * Copyright (C) 2018-2019 The Software Heritage developers + * Copyright (C) 2018-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 @@ -136,7 +136,7 @@ name: 'save_task_status', render: (data, type, row) => { if (data === 'succeed' && row.visit_date) { - let browseOriginUrl = Urls.browse_origin(row.origin_url); + let browseOriginUrl = `${Urls.browse_origin()}?origin_url=${row.origin_url}`; browseOriginUrl += `visit/${row.visit_date}/`; return `${data}`; } diff --git a/swh/web/assets/src/bundles/browse/origin-search.js b/swh/web/assets/src/bundles/browse/origin-search.js --- a/swh/web/assets/src/bundles/browse/origin-search.js +++ b/swh/web/assets/src/bundles/browse/origin-search.js @@ -35,7 +35,7 @@ clearOriginSearchResultsTable(); let table = $('#origin-search-results tbody'); for (let [i, origin] of origins.entries()) { - let browseUrl = Urls.browse_origin(origin.url); + let browseUrl = `${Urls.browse_origin()}?origin_url=${origin.url}`; let tableRow = ``; tableRow += `${encodeURI(origin.url)}`; tableRow += ``; diff --git a/swh/web/assets/src/bundles/save/index.js b/swh/web/assets/src/bundles/save/index.js --- a/swh/web/assets/src/bundles/save/index.js +++ b/swh/web/assets/src/bundles/save/index.js @@ -1,5 +1,5 @@ /** - * Copyright (C) 2018-2019 The Software Heritage developers + * Copyright (C) 2018-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 @@ -101,7 +101,7 @@ name: 'loading_task_status', render: (data, type, row) => { if (data === 'succeed' && row.visit_date) { - let browseOriginUrl = Urls.browse_origin(row.origin_url); + let browseOriginUrl = `${Urls.browse_origin()}?origin_url=${row.origin_url}`; browseOriginUrl += `visit/${row.visit_date}/`; return `${data}`; } diff --git a/swh/web/assets/src/bundles/webapp/badges.js b/swh/web/assets/src/bundles/webapp/badges.js --- a/swh/web/assets/src/bundles/webapp/badges.js +++ b/swh/web/assets/src/bundles/webapp/badges.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 @@ -10,7 +10,7 @@ let badgeLinkUrl; if (objectType === 'origin') { badgeImageUrl = Urls.swh_badge(objectType, objectPid); - badgeLinkUrl = Urls.browse_origin(objectPid); + badgeLinkUrl = `${Urls.browse_origin()}?origin_url=${objectPid}`; } else { badgeImageUrl = Urls.swh_badge_pid(objectPid); badgeLinkUrl = Urls.browse_swh_id(objectPid); 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 @@ -1,4 +1,4 @@ -# Copyright (C) 2018-2019 The Software Heritage developers +# Copyright (C) 2018-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 @@ -442,30 +442,24 @@ origin_info, timestamp, visit_id, snapshot_id ) - url_args = {"origin_url": origin_info["url"]} + query_params["origin_url"] = origin_info["url"] + + origin_visits_url = reverse("browse-origin-visits", query_params=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 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 - ) + visit_url = reverse("browse-origin-directory", query_params=query_params) visit_info["url"] = visit_url - branches_url = reverse( - "browse-origin-branches", url_args=url_args, query_params=query_params - ) + branches_url = reverse("browse-origin-branches", query_params=query_params) - releases_url = reverse( - "browse-origin-releases", url_args=url_args, query_params=query_params - ) + releases_url = reverse("browse-origin-releases", query_params=query_params) else: assert snapshot_id is not None branches, releases = get_snapshot_content(snapshot_id) @@ -629,6 +623,11 @@ return breadcrumbs +def _check_origin_url(snapshot_id, origin_url): + if snapshot_id is None and origin_url is None: + raise BadInputExc("An origin URL must be provided as query parameter.") + + def browse_snapshot_directory( request, snapshot_id=None, origin_url=None, timestamp=None, path=None ): @@ -637,6 +636,8 @@ """ try: + _check_origin_url(snapshot_id, origin_url) + snapshot_context = get_snapshot_context( snapshot_id=snapshot_id, origin_url=origin_url, @@ -836,6 +837,8 @@ """ try: + _check_origin_url(snapshot_id, origin_url) + if path is None: raise BadInputExc("The path of a content must be given as query parameter.") @@ -1028,6 +1031,8 @@ """ try: + _check_origin_url(snapshot_id, origin_url) + snapshot_context = get_snapshot_context( snapshot_id=snapshot_id, origin_url=origin_url, @@ -1171,6 +1176,8 @@ """ try: + _check_origin_url(snapshot_id, origin_url) + snapshot_context = get_snapshot_context( snapshot_id=snapshot_id, origin_url=origin_url, @@ -1284,6 +1291,9 @@ context. """ try: + + _check_origin_url(snapshot_id, origin_url) + 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 @@ -523,14 +523,12 @@ query_params = {"revision": revision_id} if snapshot_context and snapshot_context["origin_info"]: origin_info = snapshot_context["origin_info"] - url_args = {"origin_url": origin_info["url"]} + query_params["origin_url"] = origin_info["url"] 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( - "browse-origin-log", url_args=url_args, query_params=query_params - ) + revision_log_url = reverse("browse-origin-log", query_params=query_params) elif snapshot_context: url_args = {"snapshot_id": snapshot_context["snapshot_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 @@ -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 @@ -16,23 +16,23 @@ get_snapshot_context, ) from swh.web.common import service -from swh.web.common.exc import handle_view_exception +from swh.web.common.exc import handle_view_exception, BadInputExc from swh.web.common.origin_visits import get_origin_visits from swh.web.common.utils import reverse, format_utc_iso_date, parse_timestamp @browse_route( - r"origin/(?P.+)/directory/", view_name="browse-origin-directory", + r"origin/directory/", view_name="browse-origin-directory", ) -def origin_directory_browse(request, origin_url): +def origin_directory_browse(request): """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/` + The URL that points to it is :http:get:`/browse/origin/directory/` """ return browse_snapshot_directory( request, - origin_url=origin_url, + origin_url=request.GET.get("origin_url"), timestamp=request.GET.get("timestamp"), path=request.GET.get("path"), ) @@ -42,16 +42,16 @@ r"origin/(?P.+)/visit/(?P.+)/directory/", r"origin/(?P.+)/visit/(?P.+)/directory/(?P.+)/", r"origin/(?P.+)/directory/(?P.+)/", + r"origin/(?P.+)/directory/", view_name="browse-origin-directory-legacy", ) 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)/` + The URLs that point to it are + :http:get:`/browse/origin/(origin_url)/directory/[(path)/]` and + :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/directory/[(path)/]` """ return browse_snapshot_directory( request, origin_url=origin_url, timestamp=timestamp, path=path @@ -59,18 +59,18 @@ @browse_route( - r"origin/(?P.+)/content/", view_name="browse-origin-content", + r"origin/content/", view_name="browse-origin-content", ) -def origin_content_browse(request, origin_url): +def origin_content_browse(request): """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/` + The URL that points to it is :http:get:`/browse/origin/content/` """ return browse_snapshot_content( request, - origin_url=origin_url, + origin_url=request.GET.get("origin_url"), timestamp=request.GET.get("timestamp"), path=request.GET.get("path"), selected_language=request.GET.get("language"), @@ -80,80 +80,88 @@ @browse_route( r"origin/(?P.+)/visit/(?P.+)/content/(?P.+)/", r"origin/(?P.+)/content/(?P.+)/", + r"origin/(?P.+)/content/", view_name="browse-origin-content-legacy", ) 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. - The url scheme that points to it is the following: - - * :http:get:`/browse/origin/(origin_url)/content/(path)/` - * :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/content/(path)/` + The URLs that point to it are + :http:get:`/browse/origin/(origin_url)/content/(path)/` and + :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/content/(path)/` """ - language = request.GET.get("language", None) return browse_snapshot_content( request, origin_url=origin_url, timestamp=timestamp, path=path, - selected_language=language, + selected_language=request.GET.get("language"), ) @browse_route( - r"origin/(?P.+)/log/", view_name="browse-origin-log", + r"origin/log/", view_name="browse-origin-log", ) -def origin_log_browse(request, origin_url): +def origin_log_browse(request): """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/` + The URL that points to it is :http:get:`/browse/origin/log/` """ return browse_snapshot_log( - request, origin_url=origin_url, timestamp=request.GET.get("timestamp") + request, + origin_url=request.GET.get("origin_url"), + timestamp=request.GET.get("timestamp"), ) @browse_route( r"origin/(?P.+)/visit/(?P.+)/log/", + r"origin/(?P.+)/log/", view_name="browse-origin-log-legacy", ) 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 that points to it is + The URLs that point to it are + :http:get:`/browse/origin/(origin_url)/log/` and :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.+)/branches/", view_name="browse-origin-branches", + r"origin/branches/", view_name="browse-origin-branches", ) -def origin_branches_browse(request, origin_url): +def origin_branches_browse(request): """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)/branches/` + The URL that points to it is :http:get:`/browse/origin/branches/` """ return browse_snapshot_branches( - request, origin_url=origin_url, timestamp=request.GET.get("timestamp") + request, + origin_url=request.GET.get("origin_url"), + timestamp=request.GET.get("timestamp"), ) @browse_route( r"origin/(?P.+)/visit/(?P.+)/branches/", + r"origin/(?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 + The URLs that point to it are + :http:get:`/browse/origin/(origin_url)/branches/` and :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/branches/` """ @@ -161,44 +169,45 @@ @browse_route( - r"origin/(?P.+)/releases/", view_name="browse-origin-releases", + r"origin/releases/", view_name="browse-origin-releases", ) -def origin_releases_browse(request, origin_url): +def origin_releases_browse(request): """Django view that produces an HTML display of the list of releases associated to an origin for a given visit. - The URL that points to it is :http:get:`/browse/origin/(origin_url)/releases/` + The URL that points to it is :http:get:`/browse/origin/releases/` """ return browse_snapshot_releases( - request, origin_url=origin_url, timestamp=request.GET.get("timestamp") + request, + origin_url=request.GET.get("origin_url"), + timestamp=request.GET.get("timestamp"), ) @browse_route( r"origin/(?P.+)/visit/(?P.+)/releases/", + r"origin/(?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. - The URL that points to it is + The URLs that point to it are + :http:get:`/browse/origin/(origin_url)/releases/` and :http:get:`/browse/origin/(origin_url)/visit/(timestamp)/releases/` """ return browse_snapshot_releases(request, origin_url=origin_url, timestamp=timestamp) -@browse_route(r"origin/(?P.+)/visits/", view_name="browse-origin-visits") -def origin_visits_browse(request, origin_url): - """Django view that produces an HTML display of visits reporting - for a given origin. - - The url that points to it is - :http:get:`/browse/origin/(origin_url)/visits/`. - """ +def _origin_visits_browse(request, origin_url): try: + + if origin_url is None: + raise BadInputExc("An origin URL must be provided as query parameter.") + origin_info = service.lookup_origin({"url": origin_url}) origin_visits = get_origin_visits(origin_info) snapshot_context = get_snapshot_context(origin_url=origin_url) @@ -208,7 +217,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 = {"timestamp": url_date} + query_params = {"origin_url": origin_url, "timestamp": url_date} if i < len(origin_visits) - 1: if visit["date"] == origin_visits[i + 1]["date"]: query_params = {"visit_id": visit["visit"]} @@ -218,11 +227,7 @@ snapshot = visit["snapshot"] if visit["snapshot"] else "" - visit["url"] = reverse( - "browse-origin-directory", - url_args={"origin_url": origin_url}, - query_params=query_params, - ) + visit["url"] = reverse("browse-origin-directory", query_params=query_params,) if not snapshot: visit["snapshot"] = "" visit["date"] = parse_timestamp(visit["date"]).timestamp() @@ -245,14 +250,46 @@ ) -@browse_route(r"origin/(?P.+)/", view_name="browse-origin") -def origin_browse(request, origin_url): +@browse_route(r"origin/visits/", view_name="browse-origin-visits") +def origin_visits_browse(request): + """Django view that produces an HTML display of visits reporting + for a given origin. + + The URL that points to it is + :http:get:`/browse/origin/visits/`. + """ + return _origin_visits_browse(request, request.GET.get("origin_url")) + + +@browse_route( + r"origin/(?P.+)/visits/", view_name="browse-origin-visits-legacy" +) +def origin_visits_browse_legacy(request, origin_url): + """Django view that produces an HTML display of visits reporting + for a given origin. + + The URL that points to it is + :http:get:`/browse/origin/(origin_url)/visits/`. + """ + return _origin_visits_browse(request, origin_url) + + +@browse_route(r"origin/", view_name="browse-origin") +def origin_browse(request): + """Django view that redirects to the display of the latest archived + snapshot for a given software origin. + """ + last_snapshot_url = reverse("browse-origin-directory", query_params=request.GET,) + return redirect(last_snapshot_url) + + +@browse_route(r"origin/(?P.+)/", view_name="browse-origin-legacy") +def origin_browse_legacy(request, origin_url): """Django view that redirects to the display of the latest archived snapshot for a given software origin. """ last_snapshot_url = reverse( "browse-origin-directory", - url_args={"origin_url": origin_url}, - query_params=request.GET, + query_params={"origin_url": origin_url, **request.GET}, ) return redirect(last_snapshot_url) diff --git a/swh/web/browse/views/release.py b/swh/web/browse/views/release.py --- a/swh/web/browse/views/release.py +++ b/swh/web/browse/views/release.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 @@ -163,8 +163,10 @@ if origin_info: rev_directory_url = reverse( "browse-origin-directory", - url_args={"origin_url": origin_info["url"]}, - query_params={"release": release["name"]}, + query_params={ + "origin_url": origin_info["url"], + "release": release["name"], + }, ) elif snapshot_id: rev_directory_url = reverse( 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 @@ -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 @@ -44,13 +44,10 @@ def _gen_content_url(revision, query_string, path, snapshot_context): if snapshot_context: - url_args = snapshot_context["url_args"] 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 - ) + content_url = reverse("browse-origin-content", query_params=query_params) else: content_path = "%s/%s" % (revision["directory"], path) content_url = reverse( diff --git a/swh/web/misc/badges.py b/swh/web/misc/badges.py --- a/swh/web/misc/badges.py +++ b/swh/web/misc/badges.py @@ -1,4 +1,4 @@ -# 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 @@ -94,7 +94,9 @@ if object_type == ORIGIN: service.lookup_origin({"url": object_id}) right_text = "repository" - whole_link = reverse("browse-origin", url_args={"origin_url": object_id}) + whole_link = reverse( + "browse-origin", query_params={"origin_url": object_id} + ) else: # when pid is provided, object type and id will be parsed # from it diff --git a/swh/web/templates/browse/browse.html b/swh/web/templates/browse/browse.html --- a/swh/web/templates/browse/browse.html +++ b/swh/web/templates/browse/browse.html @@ -1,7 +1,7 @@ {% extends "./layout.html" %} {% comment %} -Copyright (C) 2017-2018 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 @@ -18,8 +18,8 @@ Browse archived {{ swh_object_name.lower }} {% if snapshot_context.origin_info %} for origin - - {{ snapshot_context.origin_info.url }} + + {% url 'browse-origin' %}?origin_url={{ snapshot_context.origin_info.url }} {% if snapshot_context.origin_info.url|slice:"0:4" == "http" %} 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 @@ -1,7 +1,7 @@ {% extends "./layout.html" %} {% comment %} -Copyright (C) 2017-2018 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 @@ -118,14 +118,14 @@ @@ -137,14 +137,14 @@ @@ -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
  • @@ -171,8 +171,8 @@ revision history (aka the commit log) from an origin: - - {% url 'browse-origin-log' origin_url='https://github.com/Kitware/CMake' %} + + {% url 'browse-origin-log' %}?origin_url=https://github.com/Kitware/CMake
  • 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 @@ -176,13 +176,7 @@ 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 = dict(kwargs) - query_params.pop("origin_url") branches, releases = get_snapshot_content(snapshot) releases = list(reversed(releases)) @@ -194,33 +188,27 @@ root_directory = branch["directory"] branch["url"] = reverse( f"browse-origin-{browse_context}", - url_args=url_args, query_params={"branch": branch["name"], **query_params}, ) for release in releases: release["url"] = reverse( f"browse-origin-{browse_context}", - url_args=url_args, query_params={"release": release["name"], **query_params}, ) query_params.pop("path", None) - branches_url = reverse( - "browse-origin-branches", url_args=url_args, query_params=query_params - ) - releases_url = reverse( - "browse-origin-releases", url_args=url_args, query_params=query_params - ) + branches_url = reverse("browse-origin-branches", query_params=query_params) + releases_url = reverse("browse-origin-releases", query_params=query_params) origin_visits_url = reverse( - "browse-origin-visits", url_args={"origin_url": kwargs["origin_url"]} + "browse-origin-visits", query_params={"origin_url": kwargs["origin_url"]} ) is_empty = not branches and not releases snapshot_swhid = get_swh_persistent_id("snapshot", snapshot) snapshot_sizes = {"revision": len(branches), "release": len(releases)} visit_info["url"] = reverse( - "browse-origin-directory", url_args=url_args, query_params=query_params + "browse-origin-directory", query_params=query_params ) visit_info["formatted_date"] = format_utc_iso_date(visit_info["date"]) @@ -244,7 +232,7 @@ snapshot_id=snapshot, snapshot_sizes=snapshot_sizes, snapshot_swhid=snapshot_swhid, - url_args=url_args, + url_args={}, visit_info=visit_info, ) @@ -268,9 +256,9 @@ url_args.pop("path", None) url_args.pop("timestamp", None) url_args.pop("visit_id", None) + url_args.pop("origin_url", None) query_params = dict(kwargs) - query_params.pop("origin_url", None) query_params.pop("snapshot_id", None) expected_branch = dict(base_expected_context) 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 @@ -45,13 +45,13 @@ @given(origin_with_multiple_visits()) def test_origin_visits_browse(client, archive_data, origin): - url = reverse("browse-origin-visits", url_args={"origin_url": origin["url"]}) + url = reverse("browse-origin-visits", query_params={"origin_url": origin["url"]}) resp = client.get(url) assert resp.status_code == 200 assert_template_used(resp, "browse/origin-visits.html") - url = reverse("browse-origin-visits", url_args={"origin_url": origin["url"]}) + url = reverse("browse-origin-visits", query_params={"origin_url": origin["url"]}) resp = client.get(url) assert resp.status_code == 200 @@ -63,8 +63,7 @@ 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"]}, - query_params={"timestamp": vdate}, + query_params={"origin_url": origin["url"], "timestamp": vdate}, ) assert_contains(resp, browse_dir_url) @@ -411,7 +410,9 @@ new_origin["url"], visit.visit, status="partial", snapshot=snp_dict["id"] ) - url = reverse("browse-origin-directory", url_args={"origin_url": new_origin["url"]}) + url = reverse( + "browse-origin-directory", query_params={"origin_url": new_origin["url"]} + ) rv = client.get(url) assert rv.status_code == 200 @@ -441,8 +442,7 @@ url = reverse( "browse-origin-directory", - url_args={"origin_url": new_origin["url"]}, - query_params={"branch": "invalid_branch"}, + query_params={"origin_url": new_origin["url"], "branch": "invalid_branch"}, ) rv = client.get(url) assert rv.status_code == 404 @@ -450,7 +450,7 @@ @given(new_origin()) def test_browse_visits_origin_not_found(client, new_origin): - url = reverse("browse-origin-visits", url_args={"origin_url": new_origin.url}) + url = reverse("browse-origin-visits", query_params={"origin_url": new_origin.url}) resp = client.get(url) assert resp.status_code == 404 assert_template_used(resp, "error.html") @@ -465,7 +465,7 @@ "swh.web.common.origin_visits.get_origin_visits" ) mock_get_origin_visits.return_value = [] - url = reverse("browse-origin-directory", url_args={"origin_url": origin["url"]}) + url = reverse("browse-origin-directory", query_params={"origin_url": origin["url"]}) resp = client.get(url) assert resp.status_code == 404 assert_template_used(resp, "error.html") @@ -482,8 +482,7 @@ url = reverse( "browse-origin-directory", - url_args={"origin_url": origin["url"]}, - query_params={"visit_id": 2}, + query_params={"origin_url": origin["url"], "visit_id": 2}, ) resp = client.get(url) assert resp.status_code == 404 @@ -496,8 +495,7 @@ def test_browse_origin_directory_not_found(client, origin): url = reverse( "browse-origin-directory", - url_args={"origin_url": origin["url"]}, - query_params={"path": "/invalid/dir/path/"}, + query_params={"origin_url": origin["url"], "path": "/invalid/dir/path/"}, ) resp = client.get(url) assert resp.status_code == 404 @@ -513,8 +511,7 @@ mock_get_origin_visits.return_value = [] url = reverse( "browse-origin-content", - url_args={"origin_url": origin["url"]}, - query_params={"path": "foo"}, + query_params={"origin_url": origin["url"], "path": "foo"}, ) resp = client.get(url) assert resp.status_code == 404 @@ -532,8 +529,7 @@ url = reverse( "browse-origin-content", - url_args={"origin_url": origin["url"]}, - query_params={"path": "foo", "visit_id": 2}, + query_params={"origin_url": origin["url"], "path": "foo", "visit_id": 2}, ) resp = client.get(url) assert resp.status_code == 404 @@ -559,8 +555,7 @@ url = reverse( f"browse-origin-{browse_context}", - url_args={"origin_url": origin["url"]}, - query_params={"path": "baz"}, + query_params={"origin_url": origin["url"], "path": "baz"}, ) resp = client.get(url) assert resp.status_code == 200 @@ -575,8 +570,7 @@ def test_browse_origin_content_not_found(client, origin): url = reverse( "browse-origin-content", - url_args={"origin_url": origin["url"]}, - query_params={"path": "/invalid/file/path"}, + query_params={"origin_url": origin["url"], "path": "/invalid/file/path"}, ) resp = client.get(url) assert resp.status_code == 404 @@ -590,7 +584,7 @@ "swh.web.browse.snapshot_context.get_snapshot_context" ) mock_get_snapshot_context.side_effect = NotFoundExc("Snapshot not found") - url = reverse("browse-origin-directory", url_args={"origin_url": origin["url"]}) + url = reverse("browse-origin-directory", query_params={"origin_url": origin["url"]}) resp = client.get(url) assert resp.status_code == 404 assert_template_used(resp, "error.html") @@ -610,7 +604,7 @@ "release": 0, } mock_service.lookup_origin.return_value = origin - url = reverse("browse-origin-directory", url_args={"origin_url": origin["url"]}) + url = reverse("browse-origin-directory", query_params={"origin_url": origin["url"]}) resp = client.get(url) assert resp.status_code == 200 assert_template_used(resp, "browse/directory.html") @@ -635,8 +629,7 @@ release_data = archive_data.release_get(release["target"]) url = reverse( "browse-origin-directory", - url_args={"origin_url": origin["url"]}, - query_params={"release": release_data["name"]}, + query_params={"origin_url": origin["url"], "release": release_data["name"]}, ) resp = client.get(url) @@ -653,8 +646,7 @@ invalid_release_name = "swh-foo-bar" url = reverse( "browse-origin-directory", - url_args={"origin_url": origin["url"]}, - query_params={"release": invalid_release_name}, + query_params={"origin_url": origin["url"], "release": invalid_release_name}, ) resp = client.get(url) @@ -685,8 +677,7 @@ url = reverse( "browse-origin-directory", - url_args={"origin_url": new_origin["url"]}, - query_params={"branch": branch_name}, + query_params={"origin_url": new_origin["url"], "branch": branch_name}, ) resp = client.get(url) @@ -699,7 +690,7 @@ @given(origin()) def test_origin_content_no_path(client, origin): - url = reverse("browse-origin-content", url_args={"origin_url": origin["url"]}) + url = reverse("browse-origin-content", query_params={"origin_url": origin["url"]}) resp = client.get(url) @@ -709,6 +700,23 @@ ) +def test_origin_views_no_url_query_parameter(client): + for browse_context in ( + "content", + "directory", + "log", + "branches", + "releases", + "visits", + ): + url = reverse(f"browse-origin-{browse_context}") + resp = client.get(url) + assert resp.status_code == 400 + assert_contains( + resp, "An origin URL must be provided as query parameter.", status_code=400 + ) + + def _origin_content_view_test_helper( client, origin_info, @@ -722,12 +730,10 @@ ): content_path = "/".join(content["path"].split("/")[1:]) - url_args = {"origin_url": origin_info["url"]} - if not visit_id: visit_id = origin_visits[-1]["visit"] - query_params = {"path": content_path} + query_params = {"origin_url": origin_info["url"], "path": content_path} if timestamp: query_params["timestamp"] = timestamp @@ -735,7 +741,7 @@ if visit_id: query_params["visit_id"] = visit_id - url = reverse("browse-origin-content", url_args=url_args, query_params=query_params) + url = reverse("browse-origin-content", query_params=query_params) resp = client.get(url) @@ -761,9 +767,7 @@ parse_timestamp(timestamp).isoformat(), "%Y-%m-%dT%H:%M:%SZ" ) - root_dir_url = reverse( - "browse-origin-directory", url_args=url_args, query_params=query_params - ) + root_dir_url = reverse("browse-origin-directory", query_params=query_params) assert_contains(resp, '
  • ', count=len(path_info) + 1) @@ -771,9 +775,7 @@ for p in path_info: query_params["path"] = p["path"] - dir_url = reverse( - "browse-origin-directory", url_args=url_args, query_params=query_params - ) + dir_url = reverse("browse-origin-directory", query_params=query_params) assert_contains(resp, '%s' % (dir_url, p["name"])) assert_contains(resp, "
  • %s
  • " % filename) @@ -790,9 +792,7 @@ if "path" in query_params: del query_params["path"] - origin_branches_url = reverse( - "browse-origin-branches", url_args=url_args, query_params=query_params - ) + origin_branches_url = reverse("browse-origin-branches", query_params=query_params) assert_contains( resp, @@ -800,9 +800,7 @@ % (escape(origin_branches_url), len(origin_branches)), ) - origin_releases_url = reverse( - "browse-origin-releases", url_args=url_args, query_params=query_params - ) + origin_releases_url = reverse("browse-origin-releases", query_params=query_params) assert_contains( resp, @@ -817,7 +815,7 @@ for branch in origin_branches: query_params["branch"] = branch["name"] root_dir_branch_url = reverse( - "browse-origin-content", url_args=url_args, query_params=query_params + "browse-origin-content", query_params=query_params ) assert_contains(resp, '' % root_dir_branch_url) @@ -828,12 +826,12 @@ for release in origin_releases: query_params["release"] = release["name"] root_dir_release_url = reverse( - "browse-origin-content", url_args=url_args, query_params=query_params + "browse-origin-content", query_params=query_params ) assert_contains(resp, '' % root_dir_release_url) - url = reverse("browse-origin-content", url_args=url_args, query_params=query_params) + url = reverse("browse-origin-content", query_params=query_params) resp = client.get(url) assert resp.status_code == 200 @@ -865,9 +863,7 @@ if not visit_id: visit_id = origin_visits[-1]["visit"] - url_args = {"origin_url": origin_info["url"]} - - query_params = {} + query_params = {"origin_url": origin_info["url"]} if timestamp: query_params["timestamp"] = timestamp @@ -877,9 +873,7 @@ if path: query_params["path"] = path - url = reverse( - "browse-origin-directory", url_args=url_args, query_params=query_params - ) + url = reverse("browse-origin-directory", query_params=query_params) resp = client.get(url) @@ -905,9 +899,7 @@ if path: dir_path = "%s/%s" % (path, d["name"]) query_params["path"] = dir_path - dir_url = reverse( - "browse-origin-directory", url_args=url_args, query_params=query_params, - ) + dir_url = reverse("browse-origin-directory", query_params=query_params,) assert_contains(resp, dir_url) for f in files: @@ -915,17 +907,13 @@ if path: file_path = "%s/%s" % (path, f["name"]) query_params["path"] = file_path - file_url = reverse( - "browse-origin-content", url_args=url_args, query_params=query_params - ) + file_url = reverse("browse-origin-content", query_params=query_params) assert_contains(resp, file_url) 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 - ) + root_dir_branch_url = reverse("browse-origin-directory", query_params=query_params) nb_bc_paths = 1 if path: @@ -936,23 +924,22 @@ resp, '%s' % (root_dir_branch_url, root_directory_sha1[:7]) ) - origin_branches_url = reverse( - "browse-origin-branches", url_args=url_args, query_params=query_params - ) + origin_branches_url = reverse("browse-origin-branches", query_params=query_params) assert_contains( resp, - 'Branches (%s)' % (origin_branches_url, len(origin_branches)), + 'Branches (%s)' + % (escape(origin_branches_url), len(origin_branches)), ) - origin_releases_url = reverse( - "browse-origin-releases", url_args=url_args, query_params=query_params - ) + origin_releases_url = reverse("browse-origin-releases", query_params=query_params) nb_releases = len(origin_releases) if nb_releases > 0: assert_contains( - resp, 'Releases (%s)' % (origin_releases_url, nb_releases) + resp, + 'Releases (%s)' + % (escape(origin_releases_url), nb_releases), ) if path: @@ -963,7 +950,7 @@ for branch in origin_branches: query_params["branch"] = branch["name"] root_dir_branch_url = reverse( - "browse-origin-directory", url_args=url_args, query_params=query_params + "browse-origin-directory", query_params=query_params ) assert_contains(resp, '' % root_dir_branch_url) @@ -974,7 +961,7 @@ for release in origin_releases: query_params["release"] = release["name"] root_dir_release_url = reverse( - "browse-origin-directory", url_args=url_args, query_params=query_params + "browse-origin-directory", query_params=query_params ) assert_contains(resp, '' % root_dir_release_url) @@ -991,9 +978,9 @@ def _origin_branches_test_helper(client, origin_info, origin_snapshot): - url_args = {"origin_url": origin_info["url"]} + query_params = {"origin_url": origin_info["url"]} - url = reverse("browse-origin-branches", url_args=url_args) + url = reverse("browse-origin-branches", query_params=query_params) resp = client.get(url) @@ -1003,14 +990,14 @@ origin_branches = origin_snapshot[0] origin_releases = origin_snapshot[1] - origin_branches_url = reverse("browse-origin-branches", url_args=url_args) + origin_branches_url = reverse("browse-origin-branches", query_params=query_params) assert_contains( resp, 'Branches (%s)' % (origin_branches_url, len(origin_branches)), ) - origin_releases_url = reverse("browse-origin-releases", url_args=url_args) + origin_releases_url = reverse("browse-origin-releases", query_params=query_params) nb_releases = len(origin_releases) if nb_releases > 0: @@ -1023,8 +1010,7 @@ for branch in origin_branches: browse_branch_url = reverse( "browse-origin-directory", - url_args={"origin_url": origin_info["url"]}, - query_params={"branch": branch["name"]}, + query_params={"origin_url": origin_info["url"], "branch": branch["name"]}, ) assert_contains(resp, '' % escape(browse_branch_url)) @@ -1037,9 +1023,9 @@ def _origin_releases_test_helper(client, origin_info, origin_snapshot): - url_args = {"origin_url": origin_info["url"]} + query_params = {"origin_url": origin_info["url"]} - url = reverse("browse-origin-releases", url_args=url_args) + url = reverse("browse-origin-releases", query_params=query_params) resp = client.get(url) assert resp.status_code == 200 @@ -1048,14 +1034,14 @@ origin_branches = origin_snapshot[0] origin_releases = origin_snapshot[1] - origin_branches_url = reverse("browse-origin-branches", url_args=url_args) + origin_branches_url = reverse("browse-origin-branches", query_params=query_params) assert_contains( resp, 'Branches (%s)' % (origin_branches_url, len(origin_branches)), ) - origin_releases_url = reverse("browse-origin-releases", url_args=url_args) + origin_releases_url = reverse("browse-origin-releases", query_params=query_params) nb_releases = len(origin_releases) if nb_releases > 0: @@ -1115,7 +1101,9 @@ new_origin["url"], visit.visit, status="full", snapshot=snp_dict["id"] ) - url = reverse("browse-origin-branches", url_args={"origin_url": new_origin["url"]}) + url = reverse( + "browse-origin-branches", query_params={"origin_url": new_origin["url"]} + ) resp = client.get(url) assert resp.status_code == 200 assert_template_used(resp, "browse/branches.html") diff --git a/swh/web/tests/browse/views/test_release.py b/swh/web/tests/browse/views/test_release.py --- a/swh/web/tests/browse/views/test_release.py +++ b/swh/web/tests/browse/views/test_release.py @@ -108,8 +108,10 @@ if origin_info: directory_url = reverse( "browse-origin-directory", - url_args={"origin_url": origin_info["url"]}, - query_params={"release": release_data["name"]}, + query_params={ + "origin_url": origin_info["url"], + "release": release_data["name"], + }, ) else: rev = archive_data.revision_get(release_data["target"]) diff --git a/swh/web/tests/browse/views/test_revision.py b/swh/web/tests/browse/views/test_revision.py --- a/swh/web/tests/browse/views/test_revision.py +++ b/swh/web/tests/browse/views/test_revision.py @@ -59,8 +59,7 @@ origin_revision_log_url = reverse( "browse-origin-log", - url_args={"origin_url": origin["url"]}, - query_params={"revision": revision}, + query_params={"origin_url": origin["url"], "revision": revision}, ) url = reverse( diff --git a/swh/web/tests/misc/test_badges.py b/swh/web/tests/misc/test_badges.py --- a/swh/web/tests/misc/test_badges.py +++ b/swh/web/tests/misc/test_badges.py @@ -159,7 +159,7 @@ object_type = "object" if object_type == ORIGIN and error is None: - link = reverse("browse-origin", url_args={"origin_url": object_id}) + link = reverse("browse-origin", query_params={"origin_url": object_id}) text = "repository" elif error is None: text = persistent_identifier(object_type, object_id)