diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,12 @@ *.pyc *.sw? *~ +\#* +.\#* .coverage .eggs/ +resources/test/ __pycache__ version.txt swh.web.ui.egg-info docs/build/ -resources/test/webapp.ini \ No newline at end of file diff --git a/swh/web/ui/service.py b/swh/web/ui/service.py --- a/swh/web/ui/service.py +++ b/swh/web/ui/service.py @@ -157,6 +157,9 @@ to which we append paths to (hopefully) find the entry - the relative path to the entry starting from the directory pointed by directory_sha1_git + + Raises: + NotFoundExc if the directory entry is not found """ _, sha1_git_bin = query.parse_hash_with_algorithms_or_throws( directory_sha1_git, @@ -167,7 +170,8 @@ sha1_git_bin, path_string) if not queried_dir: - return None + raise NotFoundExc(('Directory entry with path %s from %s not found') % + (path_string, directory_sha1_git)) return converters.from_directory_entry(queried_dir) diff --git a/swh/web/ui/tests/views/test_browse.py b/swh/web/ui/tests/views/test_browse.py --- a/swh/web/ui/tests/views/test_browse.py +++ b/swh/web/ui/tests/views/test_browse.py @@ -316,6 +316,97 @@ mock_api.api_directory.assert_called_once_with( 'some-sha1') + @patch('swh.web.ui.views.browse.service') + @patch('swh.web.ui.views.browse.api') + @istest + def browse_directory_relative_file(self, mock_api, mock_service): + # given + stub_entry = { + 'sha256': '240', + 'type': 'file' + } + mock_service.lookup_directory_with_path.return_value = stub_entry + stub_file = { + 'sha1_git': '123', + 'sha1': '456', + 'status': 'visible', + 'data_url': '/api/1/content/890', + 'length': 42, + 'ctime': 'Thu, 01 Oct 2015 12:13:53 GMT', + 'target': 'file.txt', + 'sha256': '148' + } + mock_api.api_content_metadata.return_value = stub_file + mock_service.lookup_content_raw.return_value = { + 'data': 'this is my file'} + + print(mock_api.api_content_metadata.return_value) + # when + rv = self.client.get('/browse/directory/sha1/path/to/dir/') + + # then + self.assertEqual(rv.status_code, 200) + self.assert_template_used('content.html') + self.assertIsNotNone(self.get_context_variable('content')) + content = self.get_context_variable('content') + # change caused by call to prepare_data_for_view + self.assertEqual(content['data_url'], '/browse/content/890') + self.assertEqual(content['data'], 'this is my file') + mock_api.api_content_metadata.assert_called_once_with('sha256:240') + mock_service.lookup_content_raw.assert_called_once_with('sha256:240') + + @patch('swh.web.ui.views.browse.service') + @patch('swh.web.ui.views.browse.api') + @istest + def browse_directory_relative_dir(self, mock_api, mock_service): + # given + mock_service.lookup_directory_with_path.return_value = { + 'sha256': '240', + 'target': 'abcd', + 'type': 'dir' + } + + stub_directory_ls = [ + {'type': 'dir', + 'target': '123', + 'name': 'some-dir-name'}, + {'type': 'file', + 'sha1': '654', + 'name': 'some-filename'}, + {'type': 'dir', + 'target': '987', + 'name': 'some-other-dirname'} + ] + mock_api.api_directory.return_value = stub_directory_ls + + # when + rv = self.client.get('/browse/directory/sha1/path/to/file/') + + # then + self.assertEqual(rv.status_code, 200) + self.assert_template_used('directory.html') + self.assertIsNotNone(self.get_context_variable('files')) + self.assertEqual(len(self.get_context_variable('files')), + len(stub_directory_ls)) + mock_api.api_directory.assert_called_once_with('abcd') + + @patch('swh.web.ui.views.browse.service') + @patch('swh.web.ui.views.browse.api') + @istest + def browse_directory_relative_not_found(self, mock_api, mock_service): + # given + mock_service.lookup_directory_with_path.side_effect = NotFoundExc( + 'Directory entry not found.') + + # when + rv = self.client.get('/browse/directory/some-sha1/some/path/') + + # then + self.assertEqual(rv.status_code, 200) + self.assert_template_used('directory.html') + self.assertEqual(self.get_context_variable('message'), + 'Directory entry not found.') + @patch('swh.web.ui.views.browse.api') @patch('swh.web.ui.views.browse.utils') @istest @@ -1448,7 +1539,8 @@ mock_api.api_entity_by_uuid.side_effect = NotFoundExc('Not found!') # when - rv = self.client.get('/browse/entity/') + rv = self.client.get('/browse/entity/' + '5f4d4c51-498a-4e28-88b3-b3e4e8396cba/') # then self.assertEqual(rv.status_code, 200) diff --git a/swh/web/ui/views/browse.py b/swh/web/ui/views/browse.py --- a/swh/web/ui/views/browse.py +++ b/swh/web/ui/views/browse.py @@ -93,7 +93,7 @@ @app.route('/browse/content/') @app.route('/browse/content//') @set_renderers(HTMLRenderer) -def browse_content(q='5d448a06f02d9de748b6b0b9620cba1bed8480da'): +def browse_content(q): """Given a hash and a checksum, display the content's meta-data. Args: @@ -181,8 +181,7 @@ # @app.route('/browse/content//origin/') @set_renderers(HTMLRenderer) -def browse_content_with_origin( - q='sha1:4320781056e5a735a39de0b8c229aea224590052'): +def browse_content_with_origin(q): """Show content information. Args: @@ -211,22 +210,45 @@ @app.route('/browse/directory/') @app.route('/browse/directory//') +@app.route('/browse/directory///') @set_renderers(HTMLRenderer) -def browse_directory(sha1_git='dcf3289b576b1c8697f2a2d46909d36104208ba3'): +def browse_directory(sha1_git, entrypath=None): """Show directory information. Args: - - sha1_git: the directory's sha1 git identifier. + - sha1_git: the directory's sha1 git identifier. If entrypath + is set, the base directory for the relative path to the entry + - entrypath: the path to the requested entry, relative to + the directory pointed by sha1_git Returns: - The content's information at sha1_git + The content's information at sha1_git, or at sha1_git/entrypath if + entrypath is set. """ env = {'sha1_git': sha1_git, 'files': []} - + # FIXME: raise the exception in lookup_directory_with_path try: - directory_files = api.api_directory(sha1_git) - env['message'] = "Listing for directory %s:" % sha1_git + if entrypath: + env['message'] = ('Listing for directory with path %s from %s:' + % (entrypath, sha1_git)) + dir_or_file = service.lookup_directory_with_path( + sha1_git, entrypath) + if dir_or_file['type'] == 'file': + fsha = 'sha256:%s' % dir_or_file['sha256'] + content = api.api_content_metadata(fsha) + content_raw = service.lookup_content_raw(fsha) + if content_raw: # FIXME: currently assuming utf8 encoding + content['data'] = content_raw['data'] + env['content'] = utils.prepare_data_for_view( + content, encoding='utf-8') + return render_template('content.html', **env) + else: + directory_files = api.api_directory(dir_or_file['target']) + env['files'] = utils.prepare_data_for_view(directory_files) + else: + env['message'] = "Listing for directory %s:" % sha1_git + directory_files = api.api_directory(sha1_git) env['files'] = utils.prepare_data_for_view(directory_files) except (NotFoundExc, BadInputExc) as e: env['message'] = str(e) @@ -237,7 +259,7 @@ @app.route('/browse/origin/') @app.route('/browse/origin//') @set_renderers(HTMLRenderer) -def browse_origin(origin_id=1): +def browse_origin(origin_id): """Browse origin with id id. """ @@ -255,7 +277,7 @@ @app.route('/browse/person/') @app.route('/browse/person//') @set_renderers(HTMLRenderer) -def browse_person(person_id=1): +def browse_person(person_id): """Browse person with id id. """ @@ -274,7 +296,7 @@ @app.route('/browse/release/') @app.route('/browse/release//') @set_renderers(HTMLRenderer) -def browse_release(sha1_git='1e951912027ea6873da6985b91e50c47f645ae1a'): +def browse_release(sha1_git): """Browse release with sha1_git. """ @@ -294,7 +316,7 @@ @app.route('/browse/revision/') @app.route('/browse/revision//') @set_renderers(HTMLRenderer) -def browse_revision(sha1_git='d770e558e21961ad6cfdf0ff7df0eb5d7d4f0754'): +def browse_revision(sha1_git): """Browse revision with sha1_git. """ @@ -513,7 +535,7 @@ '/directory//') @set_renderers(HTMLRenderer) def browse_directory_through_revision_with_origin_history( - origin_id=1, + origin_id, branch_name="refs/heads/master", ts=None, sha1_git=None, @@ -530,9 +552,9 @@ encoding = request.args.get('encoding', 'utf8') if encoding not in aliases: - env['message'] = 'Encoding %s not supported.' \ - 'Supported Encodings: %s' % ( - encoding, list(aliases.keys())) + env['message'] = (('Encoding %s not supported.' + 'Supported Encodings: %s') % ( + encoding, list(aliases.keys()))) return render_template('revision-directory.html', **env) try: @@ -563,7 +585,7 @@ '/origin/' '/ts//') @set_renderers(HTMLRenderer) -def browse_revision_with_origin(origin_id=1, +def browse_revision_with_origin(origin_id, branch_name="refs/heads/master", ts=None): """Instead of having to specify a (root) revision by SHA1_GIT, users @@ -718,7 +740,7 @@ @app.route('/browse/entity/') @app.route('/browse/entity//') @set_renderers(HTMLRenderer) -def browse_entity(uuid='5f4d4c51-498a-4e28-88b3-b3e4e8396cba'): +def browse_entity(uuid): env = {'entities': [], 'message': None}