From a109964db3ca202371ac26a3a349cbd7f0418dd0 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jun 25 2019 14:05:09 +0000 Subject: Add a create-branch action to pagure-admin Fixes #4490 Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure/cli/admin.py b/pagure/cli/admin.py index 1c64290..c327291 100644 --- a/pagure/cli/admin.py +++ b/pagure/cli/admin.py @@ -422,6 +422,46 @@ def _parser_delete_project(subparser): local_parser.set_defaults(func=do_delete_project) +def _parser_create_branch(subparser): + """ Set up the CLI argument parser for the create-branch action. + + :arg subparser: an argparse subparser allowing to have action's specific + arguments + + """ + local_parser = subparser.add_parser( + "create-branch", + help="Create the specified branch in the specified project", + ) + local_parser.add_argument( + "--user", help="User of the project (to use only on forks)" + ) + local_parser.add_argument( + "project", + help="Project to update (as namespace/project if there " + "is a namespace)", + ) + local_parser.add_argument( + "--from-branch", + default=None, + help="Name of the branch on which to base the new one", + ) + local_parser.add_argument( + "--from-commit", + default=None, + help="Commit on which to base the new branch", + ) + local_parser.add_argument( + "new_branch", help="Name of the new branch to create" + ) + local_parser.add_argument( + "action_user", + help="Username of the user doing the action (ie: creating the " + "branch)", + ) + local_parser.set_defaults(func=do_create_branch) + + def parse_arguments(args=None): """ Set-up the argument parsing. """ parser = argparse.ArgumentParser( @@ -480,6 +520,9 @@ def parse_arguments(args=None): # delete-project _parser_delete_project(subparser) + # create-branch + _parser_create_branch(subparser) + return parser.parse_args(args) @@ -1122,6 +1165,60 @@ def do_ensure_project_hooks(args): return projects +def do_create_branch(args): + """ Creates the specified git branch + + Args: + args (argparse.Namespace): Parsed arguments + """ + _log.debug("project: %s", args.project) + _log.debug("user: %s", args.user) + _log.debug("new branch: %s", args.new_branch) + _log.debug("from branch: %s", args.from_branch) + _log.debug("from commit: %s", args.from_commit) + _log.debug("user creating: %s", args.action_user) + + if not args.from_branch and not args.from_commit: + raise pagure.exceptions.PagureException( + "You must create the branch from something, either a commit " + "or another branch" + ) + if args.from_branch and args.from_commit: + raise pagure.exceptions.PagureException( + "You must create the branch from something, either a commit " + "or another branch, not from both" + ) + + # Validate users + pagure.lib.query.get_user(session, args.action_user) + + # Get the project + project = _get_project(args.project, user=args.user) + + if project is None: + raise pagure.exceptions.PagureException( + "No project found with: %s, user: %s" % (args.project, args.user) + ) + + try: + pagure.lib.git.new_git_branch( + args.action_user, + project, + args.new_branch, + from_branch=args.from_branch, + from_commit=args.from_commit, + ) + except ValueError: + if args.from_commit: + raise pagure.exceptions.PagureException( + "No commit %s found from which to branch" % (args.from_commit) + ) + else: # pragma: no-cover + raise + + print("Branch created") + + def main(): """ Start of the application. """ diff --git a/tests/test_pagure_admin.py b/tests/test_pagure_admin.py index 6f8acfb..ef9aef4 100644 --- a/tests/test_pagure_admin.py +++ b/tests/test_pagure_admin.py @@ -18,6 +18,7 @@ import subprocess # noqa import sys # noqa import unittest # noqa +import pygit2 import munch # noqa from mock import patch, MagicMock # noqa from six import StringIO # noqa @@ -1815,5 +1816,163 @@ class PagureAdminDeleteProjectTests(tests.Modeltests): self.assertEqual(len(projects), 1) +class PagureCreateBranchTests(tests.Modeltests): + """ Tests for pagure-admin create-branch """ + + populate_db = True + + def setUp(self): + """ Set up the environnment, ran before every tests. """ + super(PagureCreateBranchTests, self).setUp() + + # Create a couple of projects + tests.create_projects(self.session) + # Create their git repo + tests.create_projects_git(os.path.join(self.path, "repos"), bare=True) + + # Make the imported pagure use the correct db session + pagure.cli.admin.session = self.session + + def test_create_branch_unknown_project(self): + """ Test the read-only function of pagure-admin on an unknown + project. + """ + + args = munch.Munch( + { + "project": "foob", + "user": None, + "new_branch": "new_branch", + "from_branch": "master", + "from_commit": None, + "action_user": "pingou", + } + ) + with self.assertRaises(pagure.exceptions.PagureException) as cm: + pagure.cli.admin.do_create_branch(args) + self.assertEqual( + cm.exception.args[0], "No project found with: foob, user: None" + ) + + def test_create_branch_invalid_project(self): + """ Test the read-only function of pagure-admin on an invalid + project. + """ + + args = munch.Munch( + { + "project": "f/o/o/b", + "user": None, + "new_branch": "new_branch", + "from_branch": "master", + "from_commit": None, + "action_user": "pingou", + } + ) + with self.assertRaises(pagure.exceptions.PagureException) as cm: + pagure.cli.admin.do_create_branch(args) + self.assertEqual( + cm.exception.args[0], + 'Invalid project name, has more than one "/": f/o/o/b', + ) + + def test_create_branch_commit_and_branch_from(self): + """ Test the read-only function of pagure-admin to get status of + a non-namespaced project. + """ + + args = munch.Munch( + { + "project": "test", + "user": None, + "new_branch": "new_branch", + "from_branch": "master", + "from_commit": "foobar", + "action_user": "pingou", + } + ) + with self.assertRaises(pagure.exceptions.PagureException) as cm: + pagure.cli.admin.do_create_branch(args) + self.assertEqual( + cm.exception.args[0], + "You must create the branch from something, either a commit " + "or another branch, not from both", + ) + + def test_create_branch_no_branch_from(self): + """ Test the read-only function of pagure-admin to get status of + a non-namespaced project. + """ + + args = munch.Munch( + { + "project": "test", + "user": None, + "new_branch": "new_branch", + "from_branch": "master", + "from_commit": None, + "action_user": "pingou", + } + ) + with self.assertRaises(pagure.exceptions.PagureException) as cm: + pagure.cli.admin.do_create_branch(args) + self.assertEqual( + cm.exception.args[0], 'The "master" branch does not exist' + ) + + def test_create_branch_no_commit_from(self): + """ Test the read-only function of pagure-admin to get status of + a non-namespaced project. + """ + + args = munch.Munch( + { + "project": "test", + "user": None, + "new_branch": "new_branch", + "from_branch": None, + "from_commit": "foobar", + "action_user": "pingou", + } + ) + with self.assertRaises(pagure.exceptions.PagureException) as cm: + pagure.cli.admin.do_create_branch(args) + self.assertEqual( + cm.exception.args[0], "No commit foobar found from which to branch" + ) + + def test_create_branch_from_branch(self): + """ Test the do_create_admin_token function of pagure-admin. """ + + gitrepo_path = os.path.join(self.path, "repos", "test.git") + tests.add_content_git_repo(gitrepo_path) + + # Check branch before: + gitrepo = pygit2.Repository(gitrepo_path) + self.assertEqual(gitrepo.listall_branches(), ["master"]) + + args = munch.Munch( + { + "project": "test", + "user": None, + "new_branch": "new_branch", + "from_branch": "master", + "from_commit": None, + "action_user": "pingou", + } + ) + + with tests.capture_output() as output: + pagure.cli.admin.do_create_branch(args) + output = output.getvalue() + self.assertEqual("Branch created\n", output) + + # Check branch after: + gitrepo = pygit2.Repository(gitrepo_path) + self.assertEqual( + sorted(gitrepo.listall_branches()), ["master", "new_branch"] + ) + + if __name__ == "__main__": unittest.main(verbosity=2)