aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--cgitize/cgit.py52
-rw-r--r--cgitize/main.py1
-rw-r--r--cgitize/repo.py41
3 files changed, 70 insertions, 24 deletions
diff --git a/cgitize/cgit.py b/cgitize/cgit.py
index 6e287e9..177a5f0 100644
--- a/cgitize/cgit.py
+++ b/cgitize/cgit.py
@@ -3,11 +3,13 @@
# For details, see https://github.com/egor-tensin/cgitize.
# Distributed under the MIT License.
+from contextlib import contextmanager
from enum import Enum
import logging
import os
import os.path
import shutil
+import stat
import cgitize.utils as utils
@@ -16,12 +18,34 @@ GIT_ENV = os.environ.copy()
GIT_ENV['GIT_SSH_COMMAND'] = 'ssh -oBatchMode=yes -oLogLevel=QUIET -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null'
-def run(*args, **kwargs):
- return utils.run(*args, env=GIT_ENV, **kwargs)
-
-
-def check_output(*args, **kwargs):
- return utils.check_output(*args, env=GIT_ENV, **kwargs)
+def git(*args, **kwargs):
+ return utils.run('git', *args, env=GIT_ENV, **kwargs)
+
+
+def git_stdout(*args, **kwargs):
+ return utils.check_output('git', *args, env=GIT_ENV, **kwargs)
+
+
+@contextmanager
+def setup_git_auth(repo):
+ if not repo.url_auth:
+ yield
+ return
+ config_path = os.path.expanduser('~/.gitconfig')
+ exists = os.path.exists(config_path)
+ if exists:
+ old_permissions = stat.S_IMODE(os.stat(config_path).st_mode)
+ new_permissions = stat.S_IRUSR | stat.S_IWUSR # 0x600
+ os.chmod(config_path, new_permissions)
+ git('config', '--global', f'url.{repo.clone_url_with_auth}.insteadOf', repo.clone_url)
+ try:
+ yield
+ finally:
+ if exists:
+ git('config', '--global', '--remove-section', f'url.{repo.clone_url_with_auth}.insteadOf')
+ os.chmod(config_path, old_permissions)
+ else:
+ os.unlink(config_path)
class CGit:
@@ -101,10 +125,10 @@ class Output:
if not os.path.isdir(repo_dir):
return RepoVerdict.SHOULD_MIRROR
with utils.chdir(repo_dir):
- if not run('git', 'rev-parse', '--is-inside-work-tree', discard_output=True):
+ if not git('rev-parse', '--is-inside-work-tree', discard_output=True):
logging.warning('Not a repository, so going to mirror: %s', repo_dir)
return RepoVerdict.SHOULD_MIRROR
- success, output = check_output('git', 'config', '--get', 'remote.origin.url')
+ success, output = git_stdout('config', '--get', 'remote.origin.url')
if not success:
# Every repository managed by this script should have the
# 'origin' remote. If it doesn't, it's trash.
@@ -126,16 +150,18 @@ class Output:
except Exception as e:
logging.exception(e)
return False
- return run('git', 'clone', '--mirror', repo.clone_url, repo_dir)
+ with setup_git_auth(repo):
+ return git('clone', '--mirror', repo.clone_url, repo_dir)
def update(self, repo):
logging.info("Updating repository '%s'", repo.repo_id)
repo_dir = self.get_repo_dir(repo)
with utils.chdir(repo_dir):
- if not run('git', 'remote', 'update', '--prune'):
- return False
- if run('git', 'rev-parse', '--verify', '--quiet', 'origin/master', discard_output=True):
- if not run('git', 'reset', '--soft', 'origin/master'):
+ with setup_git_auth(repo):
+ if not git('remote', 'update', '--prune'):
+ return False
+ if git('rev-parse', '--verify', '--quiet', 'origin/master', discard_output=True):
+ if not git('reset', '--soft', 'origin/master'):
return False
return True
diff --git a/cgitize/main.py b/cgitize/main.py
index 006f235..39f370e 100644
--- a/cgitize/main.py
+++ b/cgitize/main.py
@@ -12,7 +12,6 @@ import os.path
import sys
from cgitize.cgit import CGit, Output
-from cgitize.repo import Bitbucket, GitHub, Repo
import cgitize.utils as utils
diff --git a/cgitize/repo.py b/cgitize/repo.py
index 3a2cf1e..8ecbcf5 100644
--- a/cgitize/repo.py
+++ b/cgitize/repo.py
@@ -5,6 +5,7 @@
import abc
import os.path
+from urllib.parse import urlsplit, urlunsplit
class Repo:
@@ -59,6 +60,10 @@ class Repo:
def homepage(self):
return self._homepage
+ @property
+ def url_auth(self):
+ return False
+
class HostedRepo(Repo, abc.ABC):
def __init__(self, repo_id, owner=None, desc=None, homepage=None,
@@ -102,6 +107,18 @@ class HostedRepo(Repo, abc.ABC):
return self.clone_url_ssh
return self.clone_url_https
+ @property
+ def clone_url_with_auth(self):
+ if self._via_ssh:
+ return self.clone_url_ssh
+ auth = self.url_auth
+ clone_url = self.clone_url_https
+ if not auth:
+ return clone_url
+ clone_url = urlsplit(clone_url)
+ clone_url = clone_url._replace(netloc=f'{auth}@{clone_url.netloc}')
+ return urlunsplit(clone_url)
+
class GitHub(HostedRepo):
def __init__(self, *args, **kwargs):
@@ -123,16 +140,18 @@ class GitHub(HostedRepo):
return f'https://github.com/{self.user}/{self.repo_name}'
@property
+ def url_auth(self):
+ if self._access_token is None:
+ return ''
+ return f'{self._access_token}'
+
+ @property
def clone_url_ssh(self):
return f'ssh://git@github.com/{self.user}/{self.repo_name}.git'
@property
def clone_url_https(self):
- if self._access_token is None:
- auth = ''
- else:
- auth = f'{self._access_token}@'
- return f'https://{auth}github.com/{self.user}/{self.repo_name}.git'
+ return f'https://github.com/{self.user}/{self.repo_name}.git'
class Bitbucket(HostedRepo):
@@ -155,13 +174,15 @@ class Bitbucket(HostedRepo):
return f'https://bitbucket.org/{self.user}/{self.repo_name.lower()}'
@property
+ def url_auth(self):
+ if self._app_password is None:
+ return ''
+ return f'{self.user}:{self._app_password}'
+
+ @property
def clone_url_ssh(self):
return f'ssh://git@bitbucket.org/{self.user}/{self.repo_name}.git'
@property
def clone_url_https(self):
- if self._app_password is None:
- auth = ''
- else:
- auth = f'{self.user}:{self._app_password}@'
- return f'https://{auth}bitbucket.org/{self.user}/{self.repo_name}.git'
+ return f'https://bitbucket.org/{self.user}/{self.repo_name}.git'