From bef730f5a3f7530150fac5ae176004432697514d Mon Sep 17 00:00:00 2001 From: Ondrej Nosek Date: May 25 2020 22:55:39 +0000 Subject: fedpkg fork checks if the fork already exists When the fork already exists, method will try to add remote tracked repository. Fixes: #392 JIRA: RHELCMP-381 Signed-off-by: Ondrej Nosek --- diff --git a/fedpkg/cli.py b/fedpkg/cli.py index 6e0d4ab..5a5ca3e 100644 --- a/fedpkg/cli.py +++ b/fedpkg/cli.py @@ -30,10 +30,11 @@ from six.moves.urllib_parse import urlparse from fedpkg.bugzilla import BugzillaClient from fedpkg.utils import (assert_new_tests_repo, assert_valid_epel_package, - config_get_safely, do_fork, expand_release, - get_dist_git_url, get_fedora_release_state, - get_release_branches, get_stream_branches, is_epel, - new_pagure_issue, sl_list_to_dict, verify_sls) + config_get_safely, do_add_remote, do_fork, + expand_release, get_dist_git_url, + get_fedora_release_state, get_release_branches, + get_stream_branches, is_epel, new_pagure_issue, + sl_list_to_dict, verify_sls) from pyrpkg import rpkgError from pyrpkg.cli import cliClient @@ -1094,7 +1095,10 @@ class fedpkgClient(cliClient): ) def do_distgit_fork(self): - """create fork of the distgit repository""" + """create fork of the distgit repository + That includes creating fork itself using API call and then adding + remote tracked repository + """ distgit_section = '{0}.distgit'.format(self.name) distgit_api_base_url = config_get_safely(self.config, distgit_section, "apibaseurl") distgit_remote_base_url = self.config.get( @@ -1104,19 +1108,41 @@ class fedpkgClient(cliClient): ) distgit_token = config_get_safely(self.config, distgit_section, 'token') - fork_url = do_fork( + ret = do_fork( base_url=distgit_api_base_url, - remote_base_url=distgit_remote_base_url, token=distgit_token, + repo_name=self.cmd.repo_name, + namespace=self.cmd.ns, + cli_name=self.name, + ) + + # assemble url of the repo in web browser + fork_url = '{0}/fork/{1}/{2}/{3}'.format( + distgit_api_base_url.rstrip('/'), + self.cmd.user, + self.cmd.ns, + self.cmd.repo_name, + ) + + if ret: + msg = "Fork of the repository has been created: '{0}'" + else: + msg = "Repo '{0}' already exists." + self.log.info(msg.format(fork_url)) + + ret = do_add_remote( + base_url=distgit_api_base_url, + remote_base_url=distgit_remote_base_url, username=self.cmd.user, repo=self.cmd.repo, repo_name=self.cmd.repo_name, namespace=self.cmd.ns, - cli_name=self.name, ) - if fork_url: - msg = "Fork of the repository has been created: {0}" - self.log.info(msg.format(fork_url)) + if ret: + msg = "Adding as remote '{0}'." + else: + msg = "Remote with name '{0}' already exists." + self.log.info(msg.format(self.cmd.user)) def create_buildroot_override(self): """Create a buildroot override in Bodhi""" diff --git a/fedpkg/utils.py b/fedpkg/utils.py index 8848895..561c563 100644 --- a/fedpkg/utils.py +++ b/fedpkg/utils.py @@ -135,32 +135,19 @@ def new_pagure_issue(url, token, title, body, cli_name): url.rstrip('/'), rv.json()['issue']['id']) -def do_fork(base_url, remote_base_url, token, username, repo, repo_name, - namespace, cli_name): +def do_fork(base_url, token, repo_name, namespace, cli_name): """ Creates a fork of the project. :param base_url: a string of the URL repository - :param remote_base_url: a string of the remote tracked repository :param token: a string of the API token that has rights to make a fork - :param username: a string of the (FAS) user name - :param repo: object, current project git repository :param repo_name: a string of the repository name :param namespace: a string determines a type of the repository :param cli_name: string of the CLI's name (e.g. fedpkg) - :return: a string of the URL to the created fork in the UI + :return: a bool; True when fork was created, False when already exists """ api_url = '{0}/api/0'.format(base_url.rstrip('/')) fork_url = '{0}/fork'.format(api_url) - parsed_url = urlparse(remote_base_url) - remote_url = '{0}://{1}/forks/{2}/{3}/{4}.git'.format( - parsed_url.scheme, - parsed_url.netloc, - username, - namespace, - repo_name, - ) - headers = { 'Authorization': 'token {0}'.format(token), 'Accept': 'application/json', @@ -187,6 +174,10 @@ def do_fork(base_url, remote_base_url, token, username, repo, repo_name, rv_error = rv.json().get('error') except ValueError: rv_error = rv.text + + if re.search(r"Repo .+ already exists", rv_error, re.IGNORECASE): + return False + # show hint for expired token if re.search(r"Invalid or expired token", rv_error, re.IGNORECASE): base_error_msg += '\nFor invalid or expired token refer to ' \ @@ -194,16 +185,43 @@ def do_fork(base_url, remote_base_url, token, username, repo, repo_name, 'configuration.'.format(cli_name) raise rpkgError(base_error_msg.format(rv_error)) + return True + + +def do_add_remote(base_url, remote_base_url, username, repo, repo_name, + namespace): + """ + Adds remote tracked repository + :param base_url: a string of the URL repository + :param remote_base_url: a string of the remote tracked repository + :param username: a string of the (FAS) user name + :param repo: object, current project git repository + :param repo_name: a string of the repository name + :param namespace: a string determines a type of the repository + :return: a bool; True if remote was created, False when already exists + """ + parsed_url = urlparse(remote_base_url) + remote_url = '{0}://{1}/forks/{2}/{3}/{4}.git'.format( + parsed_url.scheme, + parsed_url.netloc, + username, + namespace, + repo_name, + ) + + # check already existing remote + for remote in repo.remotes: + if remote.name == username: + return False + try: + # create remote with username as its name repo.create_remote(username, url=remote_url) except git.exc.GitCommandError as e: - error_msg = "Fork was created; during create remote:\n {0}\n {1}".format( + error_msg = "During create remote:\n {0}\n {1}".format( " ".join(e.command), e.stderr) raise rpkgError(error_msg) - - # create and return url of the repo in web browser - return '{0}/fork/{1}/{2}/{3}'.format( - base_url.rstrip('/'), username, namespace, repo_name) + return True def get_release_branches(server_url):