-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrepo.py
122 lines (95 loc) · 3.53 KB
/
repo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018 Sandro Lutz <[email protected]>
#
# This software is licensed under GPLv3, see LICENSE for details.
import os
import subprocess
from remote_repo import RemoteRepository
class Repository():
def __init__(self, source, destinations=dict()):
'''
Initialize a git repository instance
:param RemoteRepository source: Source remote repository
:param dict destinations: Destination remote repositories
'''
self.source = source
self.destinations = destinations
self.local_path = None
self._checkLocalPath()
def clone(self):
'''
Clone this repository to the local disk (cache)
:raises ConnectionError: An error has occured
'''
self._checkLocalPath()
if (self.local_path != None):
if os.path.isdir(self.local_path + '/.git'):
self.pull()
return
self.local_path = self._generateLocalPath()
proc = subprocess.Popen(['git', 'clone', '--mirror', self.source.getGitUrl(), self.local_path + '/.git'], stdout = subprocess.DEVNULL)
try:
if proc.wait() != 0:
raise ConnectionError('Cloning repository ' + self.source.git_url + ' failed')
except KeyboardInterrupt as e:
proc.kill()
raise e
def pull(self):
'''
Pull this repository to the local disk (cache)
:raises ConnectionError: if another HTTP error has occured
'''
if (self.local_path == None):
self.clone()
return
proc = subprocess.Popen(['git', 'remote', 'update', '--prune'], cwd = self.local_path, stdout = subprocess.DEVNULL)
try:
if proc.wait() != 0:
raise ConnectionError('Cloning repository ' + self.source.git_url + ' failed')
except KeyboardInterrupt as e:
proc.kill()
raise e
def push(self, remote_name=None):
'''
(Force) Push this repository to the named git hoster
:param str remote_name: Hoster name (push to all destinations if None)
:raises ConnectionError: An error has occured
'''
if (self.local_path == None):
raise RuntimeError('No local copy of the repository ' + self.source.git_url + ' exists')
self.local_path = self._generateLocalPath()
procList = list()
if remote_name != None:
if remote_name not in self.destinations:
raise RuntimeError('Remote destination \'' + remote_name + '\' not found')
procList.append(subprocess.Popen(['git', 'push', '--mirror', self.destinations[remote_name].getGitUrl()], cwd = self.local_path, stdout = subprocess.DEVNULL))
else:
for _key, remote in self.destinations.items():
procList.append(subprocess.Popen(['git', 'push', '--mirror', remote.getGitUrl()], cwd = self.local_path))
try:
for proc in procList:
value = proc.wait()
if value != 0:
raise ConnectionError('(Error ' + str(value) + ') Pushing repository ' + self.source.git_url + ' failed')
except InterruptedError:
for proc in procList:
proc.kill()
except KeyboardInterrupt:
for proc in procList:
proc.kill()
def _checkLocalPath(self):
'''
Check if repository already exists in cache
'''
path = self._generateLocalPath()
if os.path.isdir(path) and os.path.isdir(path + '/.git'):
self.local_path = path
def _generateLocalPath(self):
'''
Generate local path for this repository
:return: local path where the repository should be stored
:rtype: str
'''
param = {'source': self.source.source_name, 'name': self.source.name}
return '/tmp/git-mirror/%(source)s/%(name)s' % param