summaryrefslogtreecommitdiffstats
path: root/src/git_tftpd/git.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/git_tftpd/git.py')
-rw-r--r--src/git_tftpd/git.py86
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')