From 5b7b4629faaf52f5bc0d50b4d0d170bd99fc7e87 Mon Sep 17 00:00:00 2001 From: Carl George Date: Apr 16 2021 21:40:34 +0000 Subject: Determine username from GitLab API --- diff --git a/src/centpkg/cli.py b/src/centpkg/cli.py index ac8a849..9f58197 100755 --- a/src/centpkg/cli.py +++ b/src/centpkg/cli.py @@ -50,8 +50,8 @@ class centpkgClient(cliClient): Create a new fork of the current repository Before the operation, you need to generate an API token at - https://{1}/-/profile/personal_access_tokens, select the relevant - scope(s) and save it in your local user configuration located + https://{1}/-/profile/personal_access_tokens, select the "api" + scope and save it in your local user configuration located at ~/.config/rpkg/{0}.conf. For example: [{0}.distgit] @@ -60,11 +60,6 @@ class centpkgClient(cliClient): Below is a basic example of the command to fork a current repository: {0} fork - - Operation requires username (GITLAB_ID). by default, current logged - username is taken. It could be overridden by reusing an argument: - - {0} --user GITLAB_ID fork '''.format(self.name, urlparse(distgit_api_base_url).netloc)) fork_parser = self.subparsers.add_parser( @@ -81,14 +76,9 @@ class centpkgClient(cliClient): """ 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( - '{0}'.format(self.name), - "gitbaseurl", - vars={'user': self.cmd.user, 'repo': self.cmd.repo_name}, - ) distgit_token = config_get_safely(self.config, distgit_section, 'token') - ret = do_fork( + ret, repo_path = do_fork( logger=self.log, base_url=distgit_api_base_url, token=distgit_token, @@ -98,11 +88,9 @@ class centpkgClient(cliClient): ) # assemble url of the repo in web browser - fork_url = '{0}/{1}/centos_{2}_{3}'.format( + fork_url = '{0}/{1}'.format( distgit_api_base_url.rstrip('/'), - self.cmd.user, - self.cmd.ns, - self.cmd.repo_name, + repo_path, ) if ret: @@ -111,16 +99,22 @@ class centpkgClient(cliClient): msg = "Repo '{0}' already exists." self.log.info(msg.format(fork_url)) + distgit_remote_base_url = self.config.get( + '{0}'.format(self.name), + "gitbaseurl", + vars={'repo': '{0}/{1}'.format(self.cmd.ns, self.cmd.repo_name)}, + ) + remote_name = repo_path.split('/')[0] + 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, + repo_path=repo_path, + remote_name=remote_name, ) if ret: msg = "Adding as remote '{0}'." else: msg = "Remote with name '{0}' already exists." - self.log.info(msg.format(self.cmd.user)) + self.log.info(msg.format(remote_name)) diff --git a/src/centpkg/utils.py b/src/centpkg/utils.py index 6637201..cf98c1c 100644 --- a/src/centpkg/utils.py +++ b/src/centpkg/utils.py @@ -30,7 +30,8 @@ def do_fork(logger, base_url, token, repo_name, namespace, cli_name): :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. centpkg) - :return: a bool; True when fork was created, False when already exists + :return: a tuple consisting of whether the fork needed to be created (bool) + and the fork path (string) """ api_url = '{0}/api/v4'.format(base_url.rstrip('/')) project_id = quote_plus("redhat/centos-stream/{0}/{1}".format(namespace, repo_name)) @@ -58,7 +59,7 @@ def do_fork(logger, base_url, token, repo_name, namespace, cli_name): try: # Extract response json for debugging rv_json = rv.json() - logger.debug("Pagure API response: '{0}'".format(rv_json)) + logger.debug("GitLab API response: '{0}'".format(rv_json)) except Exception: pass @@ -66,7 +67,12 @@ def do_fork(logger, base_url, token, repo_name, namespace, cli_name): if not rv.ok: # fork was already created if rv.status_code == 409 or rv.reason == "Conflict": - return False + # When the repo already exists, the return doesn't contain the repo + # path or username. Make one more API call to get the username of + # the token to construct the repo path. + rv = requests.get('{0}/user'.format(api_url), headers=headers) + username = rv.json()['username'] + return False, '{0}/{1}'.format(username, safe_name) # show hint for invalid, expired or revoked token elif rv.status_code == 401 or rv.reason == "Unauthorized": base_error_msg += '\nFor invalid or expired token refer to ' \ @@ -74,38 +80,33 @@ def do_fork(logger, base_url, token, repo_name, namespace, cli_name): 'configuration.'.format(cli_name) raise rpkgError(base_error_msg.format(rv.text)) - return True + return True, rv_json['path_with_namespace'] -def do_add_remote(base_url, remote_base_url, username, repo, repo_name, - namespace): +def do_add_remote(base_url, remote_base_url, repo, repo_path, remote_name): """ 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 + :param repo_path: a string of the repository path + :param remote_name: a string of the remote name :return: a bool; True if remote was created, False when already exists """ parsed_url = urlparse(remote_base_url) - remote_url = '{0}://{1}/{2}/centos_{3}_{4}.git'.format( + remote_url = '{0}://{1}/{2}.git'.format( parsed_url.scheme, parsed_url.netloc, - username, - namespace, - repo_name, + repo_path, ) # check already existing remote for remote in repo.remotes: - if remote.name == username: + if remote.name == remote_name: return False try: - # create remote with username as its name - repo.create_remote(username, url=remote_url) + repo.create_remote(remote_name, url=remote_url) except git.exc.GitCommandError as e: error_msg = "During create remote:\n {0}\n {1}".format( " ".join(e.command), e.stderr)