You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
3.9 KiB
Python
139 lines
3.9 KiB
Python
import logging
|
|
import os
|
|
import os.path
|
|
import re
|
|
import shlex
|
|
import subprocess
|
|
|
|
from zope.interface import implementer
|
|
|
|
from vcs_mirrors.lib.cd import Cd
|
|
from vcs_mirrors.lib.interfaces import IRepo
|
|
from vcs_mirrors.lib.utils import run_cmd
|
|
|
|
__all__ = ['Repo']
|
|
|
|
|
|
@implementer(IRepo)
|
|
class Repo(object):
|
|
TYPE = 'git'
|
|
|
|
@staticmethod
|
|
def get_host(url):
|
|
"""
|
|
Returns the hostname when the url is a git host else None
|
|
|
|
Tested urls:
|
|
- https://github.com/pcdummy/vcs-mirrors.git
|
|
- https://git.lxch.eu/vcs-mirrors.git
|
|
- ssh://user@server/project.git
|
|
- user@server:project.git
|
|
- git://git.proxmox.com/git/aab.git
|
|
"""
|
|
url = str(url)
|
|
|
|
# https://github.com/pcdummy/vcs-mirrors.git
|
|
# https://git.lxch.eu/vcs-mirrors.git
|
|
match = re.search(r'https://([-\d\w_\.]+)/.*\.git$', url)
|
|
if match:
|
|
return match.group(1)
|
|
|
|
# ssh://user@server/project.git
|
|
match = re.search(
|
|
r'(ssh://)?[-\d\w_\.]+@{1}([-\d\w_\.]+)[:/]{1}.*\.git$', url)
|
|
if match:
|
|
return match.group(2)
|
|
|
|
# git://git.lxch.eu/git/aab.git
|
|
match = re.search(r'git://([-\d\w_\.]+)/.*\.git$', url)
|
|
if match:
|
|
return match.group(1)
|
|
|
|
return None
|
|
|
|
_config = None
|
|
|
|
def _after_clone(self):
|
|
pass
|
|
|
|
def __init__(self, config):
|
|
self._config = config
|
|
|
|
def fetch(self, repo):
|
|
logging.debug('%s: Fetching repository "%s"' % (self, repo))
|
|
|
|
repo_config = self._config['repos'][repo]
|
|
force = False
|
|
if 'force' in repo_config:
|
|
force = repo_config['force']
|
|
|
|
prune = False
|
|
if 'prune' in repo_config:
|
|
prune = repo_config['prune']
|
|
|
|
repo_dir = os.path.join(self._config['settings']['local_path'], repo)
|
|
repo_dir_exists = True
|
|
if not os.path.exists(repo_dir):
|
|
repo_dir_exists = False
|
|
logging.debug('Makedirs: "%s"', repo_dir)
|
|
os.makedirs(repo_dir, mode=0o700)
|
|
|
|
with Cd(repo_dir):
|
|
if not repo_dir_exists:
|
|
run_cmd(['git', 'clone', '--bare', shlex.quote(repo_config['source']), '.'])
|
|
run_cmd(['git', 'remote', 'rename', 'origin', 'source'])
|
|
self._after_clone()
|
|
else:
|
|
has_repo = run_cmd(['git', 'remote', 'get-url', 'source'], False).returncode == 0
|
|
if not has_repo:
|
|
run_cmd(['git', 'remote', 'add', 'source', shlex.quote(repo_config['source'])])
|
|
|
|
args = ['git', 'fetch']
|
|
if force:
|
|
args.append('--force')
|
|
if prune:
|
|
args.append('--prune')
|
|
args.append('source')
|
|
|
|
run_cmd(args)
|
|
|
|
return True
|
|
|
|
def push(self, repo):
|
|
logging.debug('%s: Pushing to repository "%s"' % (self, repo))
|
|
|
|
repo_dir = os.path.join(self._config['settings']['local_path'], repo)
|
|
if not os.path.exists(repo_dir):
|
|
logging.error('%s: Can\'t push repo "%s", it does not exists localy.' % (self, repo))
|
|
|
|
repo_config = self._config['repos'][repo]
|
|
force = False
|
|
if 'force' in repo_config:
|
|
force = repo_config['force']
|
|
|
|
prune = False
|
|
if 'prune' in repo_config:
|
|
prune = repo_config['prune']
|
|
|
|
with Cd(repo_dir):
|
|
has_repo = run_cmd(['git', 'remote', 'get-url', 'dest'], False).returncode == 0
|
|
if not has_repo:
|
|
run_cmd(['git', 'remote', 'add', 'dest', shlex.quote(repo_config['dest'])])
|
|
|
|
args = ['git', 'push']
|
|
if force:
|
|
args.append('--force')
|
|
if prune:
|
|
args.append('--prune')
|
|
args.extend(['dest', '--all'])
|
|
|
|
run_cmd(args)
|
|
|
|
return True
|
|
|
|
def __str__(self):
|
|
return self.TYPE
|
|
|
|
def __repr__(self):
|
|
return '<repo(%s)>' % self.TYPE
|