Browse Source

Add a create-branch action to pagure-admin

Fixes #4490

Signed-off-by: Pierre-Yves Chibon <pingou@pingoured.fr>
Pierre-Yves Chibon 4 years ago
parent
commit
a109964db3
2 changed files with 256 additions and 0 deletions
  1. 97 0
      pagure/cli/admin.py
  2. 159 0
      tests/test_pagure_admin.py

+ 97 - 0
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. """
 

+ 159 - 0
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)