File indexing completed on 2024-12-01 08:16:20

0001 """
0002 Base class for creating a connection to the GitLab instance used by the repository in pwd
0003 """
0004 
0005 # SPDX-FileCopyrightText: 2020 Jonah BrĂ¼chert <jbb@kaidan.im>
0006 #
0007 # SPDX-License-Identifier: GPL-2.0-or-later
0008 
0009 import sys
0010 
0011 from typing import Optional
0012 
0013 from urllib.parse import urlparse
0014 
0015 from gitlab import Gitlab
0016 from gitlab.v4.objects import Project
0017 from gitlab.exceptions import GitlabAuthenticationError, GitlabGetError, GitlabHttpError
0018 from git import Repo
0019 
0020 from lab.utils import Utils, LogType
0021 from lab.config import Config
0022 
0023 
0024 class RepositoryConnection:
0025     """
0026     Creates a connection to the gitlab instance used by the current repository
0027     """
0028 
0029     # protected
0030     _connection: Gitlab
0031     _local_repo: Repo
0032     _remote_project: Project
0033 
0034     # private
0035     __config: Config
0036 
0037     def __init__(self) -> None:
0038         self._local_repo = Utils.get_cwd_repo()
0039         self.__config = Config()
0040 
0041         try:
0042             origin = self._local_repo.remote(name="origin")
0043         except ValueError:
0044             Utils.log(LogType.ERROR, "No origin remote exists")
0045             sys.exit(1)
0046 
0047         repository: str = next(origin.urls)
0048         if repository.startswith("http"):
0049             Utils.log(
0050                 LogType.INFO,
0051                 "Found http remote, if you want to switch this "
0052                 + "repository to ssh, run `git lab rewrite-remote "
0053                 + "origin`",
0054             )
0055             print()
0056 
0057         gitlab_url = Utils.gitlab_instance_url(repository)
0058         gitlab_hostname: Optional[str] = urlparse(gitlab_url).hostname
0059 
0060         if not gitlab_hostname:
0061             Utils.log(LogType.ERROR, "Failed to detect GitLab hostname")
0062             sys.exit(1)
0063 
0064         auth_token: Optional[str] = self.__config.token(gitlab_hostname)
0065         if not auth_token:
0066             Utils.log(LogType.ERROR, "No authentication token found. ")
0067             print(
0068                 "Please create a token with the api and write_repository scopes on {}/-/{}.".format(
0069                     gitlab_url, "profile/personal_access_tokens"
0070                 )
0071             )
0072             print('Afterwards use "git lab login --host {} --token t0k3n"'.format(gitlab_hostname))
0073             sys.exit(1)
0074 
0075         self.__login(gitlab_url, auth_token)
0076         if not self._connection:
0077             Utils.log(LogType.ERROR, "Failed to connect to GitLab")
0078             sys.exit(1)
0079 
0080         try:
0081             self._remote_project = self._connection.projects.get(Utils.str_id_for_url(repository))
0082         except (GitlabHttpError, GitlabGetError):
0083             Utils.log(
0084                 LogType.ERROR,
0085                 "The repository could not be found on the GitLab instance.",
0086             )
0087             print(
0088                 "If the repository was recently moved, please update the origin remote using git."
0089             )
0090             sys.exit(1)
0091 
0092     def __login(self, hostname: str, token: str) -> None:
0093         try:
0094             self._connection: Gitlab = Gitlab(hostname, private_token=token)
0095             self._connection.auth()
0096         except (GitlabAuthenticationError, GitlabGetError):
0097             Utils.log(LogType.ERROR, "Could not log into GitLab: {}".format(hostname))
0098             sys.exit(1)