diff options
Diffstat (limited to 'src/git_tftpd/git.py')
-rw-r--r-- | src/git_tftpd/git.py | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/git_tftpd/git.py b/src/git_tftpd/git.py new file mode 100644 index 0000000..695ccb5 --- /dev/null +++ b/src/git_tftpd/git.py @@ -0,0 +1,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') |