mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
- 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 <veiko17@disroot.org>
[sunil@medhas.org Remove unneeded #! directive]
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
234 lines
8.1 KiB
Python
Executable File
234 lines
8.1 KiB
Python
Executable File
#!/usr/bin/python3
|
||
#
|
||
# 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 <http://www.gnu.org/licenses/>.
|
||
#
|
||
"""
|
||
Configuration helper for Gitweb.
|
||
"""
|
||
|
||
import argparse
|
||
import configparser
|
||
import json
|
||
import os
|
||
import shutil
|
||
import subprocess
|
||
|
||
from plinth import action_utils
|
||
from plinth.modules.gitweb.manifest import GIT_REPO_PATH
|
||
|
||
|
||
def parse_arguments():
|
||
"""Return parsed command line arguments as dictionary."""
|
||
parser = argparse.ArgumentParser()
|
||
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
|
||
|
||
subparsers.add_parser(
|
||
'setup', help='Perform post-installation operations for Gitweb')
|
||
|
||
subparser = subparsers.add_parser('create-repo',
|
||
help='Create a new repository')
|
||
subparser.add_argument('--name', required=True,
|
||
help='Name of the repository')
|
||
subparser.add_argument('--description', required=True,
|
||
help='Description of the repository')
|
||
subparser.add_argument('--owner', required=True,
|
||
help='Repository’s owner name')
|
||
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')
|
||
subparser.add_argument('--name', required=True,
|
||
help='Name of the repository')
|
||
|
||
subparser = subparsers.add_parser('rename-repo',
|
||
help='Rename an repository')
|
||
subparser.add_argument('--oldname', required=True,
|
||
help='Old name of the repository')
|
||
subparser.add_argument('--newname', required=True,
|
||
help='New name of the repository')
|
||
|
||
subparser = subparsers.add_parser('set-repo-description',
|
||
help='Set description of the repository')
|
||
subparser.add_argument('--name', required=True,
|
||
help='Name of the repository')
|
||
subparser.add_argument('--description', required=True,
|
||
help='Description of the repository')
|
||
|
||
subparser = subparsers.add_parser('set-repo-owner',
|
||
help='Set repository\'s owner name')
|
||
subparser.add_argument('--name', required=True,
|
||
help='Name of the repository')
|
||
subparser.add_argument('--owner', required=True,
|
||
help='Repository’s owner name')
|
||
|
||
subparser = subparsers.add_parser(
|
||
'set-repo-access', help='Set repository as private or public')
|
||
subparser.add_argument('--name', required=True,
|
||
help='Name of the repository')
|
||
subparser.add_argument('--access', required=True,
|
||
choices=['public', 'private'], help='Access status')
|
||
|
||
subparser = subparsers.add_parser('delete-repo',
|
||
help='Delete an existing repository')
|
||
subparser.add_argument('--name', required=True,
|
||
help='Name of the repository to remove')
|
||
|
||
subparsers.required = True
|
||
return parser.parse_args()
|
||
|
||
|
||
def subcommand_setup(_):
|
||
"""Disable default Apache2 Gitweb configuration"""
|
||
action_utils.webserver_disable('gitweb')
|
||
|
||
|
||
def _get_repo_description(repo):
|
||
"""Set description of the repository."""
|
||
description_file = os.path.join(GIT_REPO_PATH, repo + '.git',
|
||
'description')
|
||
if os.path.exists(description_file):
|
||
with open(description_file, 'r') as file_handle:
|
||
description = file_handle.read()
|
||
else:
|
||
description = ''
|
||
|
||
return description
|
||
|
||
|
||
def _set_repo_description(repo, description):
|
||
"""Set description of the repository."""
|
||
description_file = os.path.join(GIT_REPO_PATH, repo + '.git',
|
||
'description')
|
||
with open(description_file, 'w') as file_handle:
|
||
file_handle.write(description)
|
||
|
||
|
||
def _get_repo_owner(repo):
|
||
"""Set repository's owner name."""
|
||
repo_config = os.path.join(GIT_REPO_PATH, repo + '.git', 'config')
|
||
config = configparser.ConfigParser()
|
||
config.read(repo_config)
|
||
try:
|
||
owner = config['gitweb']['owner']
|
||
except KeyError:
|
||
owner = ''
|
||
|
||
return owner
|
||
|
||
|
||
def _set_repo_owner(repo, owner):
|
||
"""Set repository's owner name."""
|
||
repo_config = os.path.join(GIT_REPO_PATH, repo + '.git', 'config')
|
||
config = configparser.ConfigParser()
|
||
config.read(repo_config)
|
||
if not config.has_section('gitweb'):
|
||
config.add_section('gitweb')
|
||
|
||
config['gitweb']['owner'] = owner
|
||
with open(repo_config, 'w') as file_handle:
|
||
config.write(file_handle)
|
||
|
||
|
||
def _get_access_status(repo):
|
||
"""Get repository's access status"""
|
||
private_file = os.path.join(GIT_REPO_PATH, repo + '.git', 'private')
|
||
if os.path.exists(private_file):
|
||
return 'private'
|
||
|
||
return 'public'
|
||
|
||
|
||
def _set_access_status(repo, status):
|
||
"""Set repository as private or public"""
|
||
private_file = os.path.join(GIT_REPO_PATH, repo + '.git', 'private')
|
||
if status == 'private':
|
||
open(private_file, 'a')
|
||
elif status == 'public':
|
||
if os.path.exists(private_file):
|
||
os.remove(private_file)
|
||
|
||
|
||
def subcommand_rename_repo(arguments):
|
||
"""Rename a repository."""
|
||
oldpath = os.path.join(GIT_REPO_PATH, arguments.oldname + '.git')
|
||
newpath = os.path.join(GIT_REPO_PATH, arguments.newname + '.git')
|
||
os.rename(oldpath, newpath)
|
||
|
||
|
||
def subcommand_set_repo_description(arguments):
|
||
"""Set description of the repository."""
|
||
_set_repo_description(arguments.name, arguments.description)
|
||
|
||
|
||
def subcommand_set_repo_owner(arguments):
|
||
"""Set repository's owner name."""
|
||
_set_repo_owner(arguments.name, arguments.owner)
|
||
|
||
|
||
def subcommand_set_repo_access(arguments):
|
||
"""Set repository's access status."""
|
||
_set_access_status(arguments.name, arguments.access)
|
||
|
||
|
||
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(
|
||
arguments.name), owner=_get_repo_owner(arguments.name),
|
||
access=_get_access_status(arguments.name))))
|
||
|
||
|
||
def subcommand_create_repo(arguments):
|
||
"""Create a new git repository."""
|
||
os.chdir(GIT_REPO_PATH)
|
||
repo_name = arguments.name + '.git'
|
||
subprocess.check_call(['git', 'init', '--bare', 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:
|
||
_set_access_status(arguments.name, 'private')
|
||
|
||
|
||
def subcommand_delete_repo(arguments):
|
||
"""Delete a git repository."""
|
||
repo_path = os.path.join(GIT_REPO_PATH, arguments.name + '.git')
|
||
shutil.rmtree(repo_path)
|
||
|
||
|
||
def main():
|
||
"""Parse arguments and perform all duties."""
|
||
arguments = parse_arguments()
|
||
|
||
subcommand = arguments.subcommand.replace('-', '_')
|
||
subcommand_method = globals()['subcommand_' + subcommand]
|
||
subcommand_method(arguments)
|
||
|
||
|
||
if __name__ == '__main__':
|
||
main()
|