From 207de1941efa156de8c00766040622cd6d8c7226 Mon Sep 17 00:00:00 2001 From: vapao Date: Tue, 2 Jun 2020 20:03:01 +0800 Subject: [PATCH] =?UTF-8?q?U=20=E4=BC=98=E5=8C=96git=20clone=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E4=B8=8A=E4=BC=A0=E7=9A=84=E5=AF=86=E9=92=A5=E5=AF=B9?= =?UTF-8?q?=E4=BD=9C=E4=B8=BA=E5=A4=87=E9=80=89=E5=AF=86=E9=92=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spug_api/apps/app/utils.py | 8 +++++- spug_api/libs/gitlib.py | 57 ++++++++++++++++++++++++++++++-------- 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/spug_api/apps/app/utils.py b/spug_api/apps/app/utils.py index 30150cc9..bc02905e 100644 --- a/spug_api/apps/app/utils.py +++ b/spug_api/apps/app/utils.py @@ -3,6 +3,7 @@ # Released under the MIT License. from django.conf import settings from apps.app.models import Deploy +from apps.setting.utils import AppSetting from libs.gitlib import Git import shutil import os @@ -22,7 +23,12 @@ def parse_envs(text): def fetch_versions(deploy: Deploy): git_repo = deploy.extend_obj.git_repo repo_dir = os.path.join(settings.REPOS_DIR, str(deploy.id)) - return Git(git_repo, repo_dir).fetch_branches_tags() + try: + pkey = AppSetting.get('private_key') + except KeyError: + pkey = None + with Git(git_repo, repo_dir, pkey) as git: + return git.fetch_branches_tags() def remove_repo(deploy_id): diff --git a/spug_api/libs/gitlib.py b/spug_api/libs/gitlib.py index 096d8a31..f643b5de 100644 --- a/spug_api/libs/gitlib.py +++ b/spug_api/libs/gitlib.py @@ -1,21 +1,27 @@ # Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug # Copyright: (c) # Released under the MIT License. -from git import Repo, RemoteReference, TagReference, InvalidGitRepositoryError +from git import Repo, RemoteReference, TagReference, InvalidGitRepositoryError, GitCommandError +from tempfile import NamedTemporaryFile import shutil import os class Git: - def __init__(self, git_repo, repo_dir): - self.repo = self._get_repo(git_repo, repo_dir) + def __init__(self, git_repo, repo_dir, pkey=None): + self.git_repo = git_repo + self.repo_dir = repo_dir + self.repo = None + self.pkey = pkey + self.fd = None + self.env = {} def archive(self, filepath, commit): with open(filepath, 'wb') as f: self.repo.archive(f, commit) def fetch_branches_tags(self): - self.repo.remotes.origin.fetch() + self._fetch() branches, tags = {}, {} for ref in self.repo.references: if isinstance(ref, RemoteReference): @@ -36,16 +42,32 @@ def fetch_branches_tags(self): tags = sorted(tags.items(), key=lambda x: x[1]['date'], reverse=True) return branches, dict(tags) - def _get_repo(self, git_repo, repo_dir): - if os.path.exists(repo_dir): + def _fetch(self): + try: + self.repo.remotes.origin.fetch() + except GitCommandError as e: + if self.env: + self.repo.remotes.origin.fetch(env=self.env) + else: + raise e + + def _get_repo(self): + if os.path.exists(self.repo_dir): try: - return Repo(repo_dir) + return Repo(self.repo_dir) except InvalidGitRepositoryError: - if os.path.isdir(repo_dir): - shutil.rmtree(repo_dir) + if os.path.isdir(self.repo_dir): + shutil.rmtree(self.repo_dir) else: - os.remove(repo_dir) - return Repo.clone_from(git_repo, repo_dir) + os.remove(self.repo_dir) + try: + repo = Repo.clone_from(self.git_repo, self.repo_dir) + except GitCommandError as e: + if self.env: + repo = Repo.clone_from(self.git_repo, self.repo_dir, env=self.env) + else: + raise e + return repo def _get_commits(self, branch, count=10): commits = [] @@ -59,3 +81,16 @@ def _get_commits(self, branch, count=10): 'message': commit.message.strip() }) return commits + + def __enter__(self): + if self.pkey: + self.fd = NamedTemporaryFile() + self.fd.write(self.pkey.encode()) + self.fd.flush() + self.env = {'GIT_SSH_COMMAND': f'ssh -i {self.fd.name}'} + self.repo = self._get_repo() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if self.fd: + self.fd.close()