diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js index 84c1803bcf..af10b8371f 100644 --- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js +++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js @@ -1498,11 +1498,28 @@ */ getRepos(filter, reposPerPage, opt_offset) { const defaultFilter = 'state:active OR state:read-only'; + const namePartDelimiters = /[@.\-\s\/_]/g; const offset = opt_offset || 0; + if (filter && !filter.includes(':') && filter.match(namePartDelimiters)) { + // The query language specifies hyphens as operators. Split the string + // by hyphens and 'AND' the parts together as 'inname:' queries. + // If the filter includes a semicolon, the user is using a more complex + // query so we trust them and don't do any magic under the hood. + const originalFilter = filter; + filter = ''; + originalFilter.split(namePartDelimiters).forEach(part => { + if (part) { + filter += (filter === '' ? 'inname:' : ' AND inname:') + part; + } + }); + } + // Check if filter is now empty which could be either because the user did + // not provide it or because the user provided only a split character. if (!filter) { filter = defaultFilter; } + filter = filter.trim(); const encodedFilter = encodeURIComponent(filter); diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html index b7466efec0..d9656e4758 100644 --- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html +++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html @@ -951,16 +951,46 @@ limitations under the License. '/projects/?n=26&S=25&query=test'); }); - test('with filter', () => { - element.getRepos('test/test/test', 25); + test('with blank', () => { + element.getRepos('test/test', 25); assert.equal(element._fetchSharedCacheURL.lastCall.args[0].url, - '/projects/?n=26&S=0&query=test%2Ftest%2Ftest'); + '/projects/?n=26&S=0&query=inname%3Atest%20AND%20inname%3Atest'); }); - test('with regex filter', () => { - element.getRepos('^test.*', 25); + test('with hyphen', () => { + element.getRepos('foo-bar', 25); assert.equal(element._fetchSharedCacheURL.lastCall.args[0].url, - '/projects/?n=26&S=0&query=%5Etest.*'); + '/projects/?n=26&S=0&query=inname%3Afoo%20AND%20inname%3Abar'); + }); + + test('with leading hyphen', () => { + element.getRepos('-bar', 25); + assert.equal(element._fetchSharedCacheURL.lastCall.args[0].url, + '/projects/?n=26&S=0&query=inname%3Abar'); + }); + + test('with trailing hyphen', () => { + element.getRepos('foo-bar-', 25); + assert.equal(element._fetchSharedCacheURL.lastCall.args[0].url, + '/projects/?n=26&S=0&query=inname%3Afoo%20AND%20inname%3Abar'); + }); + + test('with underscore', () => { + element.getRepos('foo_bar', 25); + assert.equal(element._fetchSharedCacheURL.lastCall.args[0].url, + '/projects/?n=26&S=0&query=inname%3Afoo%20AND%20inname%3Abar'); + }); + + test('with underscore', () => { + element.getRepos('foo_bar', 25); + assert.equal(element._fetchSharedCacheURL.lastCall.args[0].url, + '/projects/?n=26&S=0&query=inname%3Afoo%20AND%20inname%3Abar'); + }); + + test('hyphen only', () => { + element.getRepos('-', 25); + assert.equal(element._fetchSharedCacheURL.lastCall.args[0].url, + `/projects/?n=26&S=0&query=${defaultQuery}`); }); });