From c8eb5bb3cab8a30aee5d36d0f4c1c04beca5e408 Mon Sep 17 00:00:00 2001 From: Veiko Aasa Date: Tue, 22 Oct 2019 11:53:34 +0300 Subject: [PATCH] gitweb: Add tests for actions script - add tests for create, edit and delete repository functions - modify actions script to allow run actions without root privileges: - add argument --git-repo-root to overwrite the default root directory of repositories - add option --keep-ownership to the create-repo command to skip changing ownership to www-data - actions script, repo-info command: instead of returning empty values, raise an error if the repository doesn't exist Closes #1667 Signed-off-by: Veiko Aasa [sunil@medhas.org Remove unneeded #! directive] Signed-off-by: Sunil Mohan Adapa Reviewed-by: Sunil Mohan Adapa --- actions/gitweb | 10 ++- plinth/modules/gitweb/tests/test_gitweb.py | 93 ++++++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 plinth/modules/gitweb/tests/test_gitweb.py diff --git a/actions/gitweb b/actions/gitweb index b00926b93..3771781f8 100755 --- a/actions/gitweb +++ b/actions/gitweb @@ -49,6 +49,9 @@ def parse_arguments(): subparser.add_argument( '--is-private', required=False, default=False, action='store_true', help='Allow only authorized users to access this repository') + subparser.add_argument( + '--keep-ownership', required=False, default=False, action="store_true", + help='Do not chanege ownership of the repository directory') subparser = subparsers.add_parser( 'repo-info', help='Get information about the repository') @@ -187,6 +190,10 @@ def subcommand_set_repo_access(arguments): def subcommand_repo_info(arguments): """Get information about repository.""" + repo_path = os.path.join(GIT_REPO_PATH, arguments.name + '.git') + if not os.path.exists(repo_path): + raise RuntimeError('Repository not found') + print( json.dumps( dict(name=arguments.name, description=_get_repo_description( @@ -199,7 +206,8 @@ def subcommand_create_repo(arguments): os.chdir(GIT_REPO_PATH) repo_name = arguments.name + '.git' subprocess.check_call(['git', 'init', '--bare', repo_name]) - subprocess.check_call(['chown', '-R', 'www-data:www-data', repo_name]) + if not arguments.keep_ownership: + subprocess.check_call(['chown', '-R', 'www-data:www-data', repo_name]) _set_repo_description(arguments.name, arguments.description) _set_repo_owner(arguments.name, arguments.owner) if arguments.is_private: diff --git a/plinth/modules/gitweb/tests/test_gitweb.py b/plinth/modules/gitweb/tests/test_gitweb.py new file mode 100644 index 000000000..2b389b5e7 --- /dev/null +++ b/plinth/modules/gitweb/tests/test_gitweb.py @@ -0,0 +1,93 @@ +# +# This file is part of FreedomBox. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +""" +Test module for gitweb module operations. +""" + +import imp +import json +import pathlib +from unittest.mock import patch + +import pytest + + +def _action_file(): + """Return the path to the 'gitweb' actions file.""" + current_directory = pathlib.Path(__file__).parent + return str( + current_directory / '..' / '..' / '..' / '..' / 'actions' / 'gitweb') + + +gitweb_actions = imp.load_source('gitweb', _action_file()) + + +@pytest.fixture(name='call_action') +def fixture_call_action(tmpdir, capsys): + """Run actions with custom repo root path.""" + + def _call_action(args, **kwargs): + gitweb_actions.GIT_REPO_PATH = str(tmpdir) + with patch('argparse._sys.argv', ['gitweb'] + args): + gitweb_actions.main() + captured = capsys.readouterr() + return captured.out + + return _call_action + + +def test_actions(call_action): + """Test gitweb actions script.""" + repo = 'Test-repo' + repo_renamed = 'Test-repo_2' + data = { + 'name': repo, + 'description': 'Test description', + 'owner': 'Test owner', + 'access': 'private' + } + + # Create repository + call_action([ + 'create-repo', '--name', repo, '--description', data['description'], + '--owner', data['owner'], '--is-private', '--keep-ownership' + ]) + assert json.loads(call_action(['repo-info', '--name', repo])) == data + + # Change metadata + data['description'] = 'Test description 2' + data['owner'] = 'Test owner 2' + data['access'] = 'public' + call_action([ + 'set-repo-description', '--name', repo, '--description', + data['description'] + ]) + call_action(['set-repo-owner', '--name', repo, '--owner', data['owner']]) + call_action( + ['set-repo-access', '--name', repo, '--access', data['access']]) + assert json.loads(call_action(['repo-info', '--name', repo])) == data + + # Rename repository + call_action(['rename-repo', '--oldname', repo, '--newname', repo_renamed]) + with pytest.raises(RuntimeError, match='Repository not found'): + call_action(['repo-info', '--name', repo]) + assert call_action(['repo-info', '--name', repo_renamed]) + + # Delete repository + call_action(['delete-repo', '--name', repo_renamed]) + with pytest.raises(RuntimeError, match='Repository not found'): + call_action(['repo-info', '--name', repo_renamed])