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
|
import os
from dulwich.client import get_transport_and_path
from dulwich.errors import UpdateRefsError, SendPackError
from dulwich.refs import SYMREF
from dulwich.repo import Repo
from twisted.python import log
LOCAL_BRANCH_PREFIX = 'refs/heads/'
REMOTE_BRANCH_PREFIX = 'refs/remotes/'
class GitRepo(object):
""" Simple high-level wrapper for dulwich. """
def __init__(self, repo):
self.path = repo
self.repo = Repo(repo)
def stage(self, filenames):
paths = [os.path.relpath(filename, self.path)
for filename in filenames]
log.msg('Staging: %s' % ', '.join(paths), system='git')
self.repo.stage(paths)
def has_changed(self):
head = self.repo.object_store[self.repo.head()]
index = self.repo.open_index()
if any(index.changes_from_tree(self.repo.object_store, head.tree)):
return True
log.msg('No changes', system='git')
return False
def commit(self, message, committer):
log.msg('Committing: %s' % message, system='git')
self.repo.do_commit(message, committer=committer)
def _get_git_remote_url(self, remote_name):
try:
config = self.repo.get_config()
return config.get(("remote", remote_name), "url")
except KeyError:
pass
return None
def _get_git_branch(self):
contents = self.repo.refs.read_ref('HEAD')
if not contents.startswith(SYMREF):
return None
refname = contents[len(SYMREF):]
if refname.startswith(LOCAL_BRANCH_PREFIX):
return refname[len(LOCAL_BRANCH_PREFIX):]
return refname
def push(self, remote):
remote_location = self._get_git_remote_url(remote)
if remote_location is not None:
branch = self._get_git_branch()
local_ref = '%s%s' % (LOCAL_BRANCH_PREFIX, branch)
log.msg('Pushing %s to %s' % (branch, remote_location),
system='git')
def update_refs(refs):
refs[local_ref] = self.repo.refs['HEAD']
return refs
client, path = get_transport_and_path(remote_location)
try:
new_refs = client.send_pack(
path, update_refs,
self.repo.object_store.generate_pack_contents)
# update remote refs
if local_ref in new_refs:
remote_ref = '%s%s/%s' % (REMOTE_BRANCH_PREFIX,
remote, branch)
self.repo.refs[remote_ref] = new_refs[local_ref]
except (UpdateRefsError, SendPackError) as e:
log.err(e, system='git')
else:
log.msg('Not pushing, origin remote not found', system='git')
|