summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Server/Plugins/Git.py
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2012-11-15 10:09:47 -0500
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2012-11-16 09:57:53 -0500
commit5d58c0435d8d3889d5fa889a65b61565da0a95f6 (patch)
tree63970841f9532920f546e7f9467f1931297f9e50 /src/lib/Bcfg2/Server/Plugins/Git.py
parent6b289ac1814e0ff450876e6575a621902a78b381 (diff)
downloadbcfg2-5d58c0435d8d3889d5fa889a65b61565da0a95f6.tar.gz
bcfg2-5d58c0435d8d3889d5fa889a65b61565da0a95f6.tar.bz2
bcfg2-5d58c0435d8d3889d5fa889a65b61565da0a95f6.zip
Git: only support GitPython; only support Git.Update with GitPython
dulwich is terrible. impressively so. git pull has a bug that prevents it from honoring --work-tree in many, many versions
Diffstat (limited to 'src/lib/Bcfg2/Server/Plugins/Git.py')
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Git.py139
1 files changed, 26 insertions, 113 deletions
diff --git a/src/lib/Bcfg2/Server/Plugins/Git.py b/src/lib/Bcfg2/Server/Plugins/Git.py
index 5faa6c018..61d581009 100644
--- a/src/lib/Bcfg2/Server/Plugins/Git.py
+++ b/src/lib/Bcfg2/Server/Plugins/Git.py
@@ -1,119 +1,15 @@
""" The Git plugin provides a revision interface for Bcfg2 repos using
git. """
-import os
import sys
import Bcfg2.Server.Plugin
-
-
-class GitAPIBase(object):
- """ Base class for the various Git APIs (dulwich, GitPython,
- subprocesses) """
- def __init__(self, path):
- self.path = path
-
- def revision(self):
- """ Get the current revision of the git repo as a string """
- raise NotImplementedError
-
- def pull(self):
- """ Pull the latest version of the upstream git repo and
- rebase against it. """
- raise NotImplementedError
-
+from subprocess import Popen, PIPE
try:
- from dulwich.client import get_transport_and_path
- from dulwich.repo import Repo
- from dulwich.file import GitFile, ensure_dir_exists
-
- class GitAPI(GitAPIBase):
- """ API for :class:`Git` using :mod:`dulwich` """
- def __init__(self, path):
- GitAPIBase.__init__(self, path)
- self.repo = Repo(self.path)
- self.client, self.origin_path = get_transport_and_path(
- self.repo.get_config().get(("remote", "origin"),
- "url"))
-
- def revision(self):
- return self.repo.head()
-
- def pull(self):
- try:
- remote_refs = self.client.fetch(
- self.origin_path, self.repo,
- determine_wants=self.repo.object_store.determine_wants_all)
- except KeyError:
- etype, err = sys.exc_info()[:2]
- # try to work around bug
- # https://bugs.launchpad.net/dulwich/+bug/1025886
- try:
- # pylint: disable=W0212
- self.client._fetch_capabilities.remove('thin-pack')
- # pylint: enable=W0212
- except KeyError:
- raise etype(err)
- remote_refs = self.client.fetch(
- self.origin_path, self.repo,
- determine_wants=self.repo.object_store.determine_wants_all)
-
- tree_id = self.repo[remote_refs['HEAD']].tree
- # iterate over tree content, giving path and blob sha.
- for entry in self.repo.object_store.iter_tree_contents(tree_id):
- entry_in_path = entry.in_path(self.repo.path)
- ensure_dir_exists(os.path.split(entry_in_path.path)[0])
- GitFile(entry_in_path.path,
- 'wb').write(self.repo[entry.sha].data)
-
+ import git
+ HAS_GITPYTHON = True
except ImportError:
- try:
- import git
-
- class GitAPI(GitAPIBase):
- """ API for :class:`Git` using :mod:`git` (GitPython) """
- def __init__(self, path):
- GitAPIBase.__init__(self, path)
- self.repo = git.Repo(path)
-
- def revision(self):
- return self.repo.head.commit.hexsha
-
- def pull(self):
- self.repo.git.pull("--rebase")
-
- except ImportError:
- from subprocess import Popen, PIPE
-
- try:
- Popen(["git"], stdout=PIPE, stderr=PIPE).wait()
-
- class GitAPI(GitAPIBase):
- """ API for :class:`Git` using subprocess to run git
- commands """
- def revision(self):
- proc = Popen(["git", "--work-tree",
- os.path.join(self.path, ".git"),
- "rev-parse", "HEAD"], stdout=PIPE,
- stderr=PIPE)
- rv, err = proc.communicate()
- if proc.wait():
- raise Exception("Git: Error getting revision from %s: "
- "%s" % (self.path, err))
- return rv.strip() # pylint: disable=E1103
-
- def pull(self):
- proc = Popen(["git", "--work-tree",
- os.path.join(self.path, ".git"),
- "pull", "--rebase"], stdout=PIPE,
- stderr=PIPE)
- err = proc.communicate()[1].strip()
- if proc.wait():
- raise Exception("Git: Error pulling: %s" % err)
-
- except OSError:
- raise ImportError("Could not import dulwich or GitPython "
- "libraries, and no 'git' command found in PATH")
+ HAS_GITPYTHON = False
class Git(Bcfg2.Server.Plugin.Version):
@@ -121,21 +17,38 @@ class Git(Bcfg2.Server.Plugin.Version):
using git. """
__author__ = 'bcfg-dev@mcs.anl.gov'
__vcs_metadata_path__ = ".git"
- __rmi__ = Bcfg2.Server.Plugin.Version.__rmi__ + ['Update']
+ if HAS_GITPYTHON:
+ __rmi__ = Bcfg2.Server.Plugin.Version.__rmi__ + ['Update']
def __init__(self, core, datastore):
Bcfg2.Server.Plugin.Version.__init__(self, core, datastore)
- self.repo = GitAPI(self.vcs_root)
+ if HAS_GITPYTHON:
+ self.repo = git.Repo(self.vcs_root)
+ else:
+ self.logger.debug("Git: GitPython not found, using CLI interface "
+ "to Git")
+ self.repo = None
self.logger.debug("Initialized git plugin with git directory %s" %
self.vcs_path)
def get_revision(self):
"""Read git revision information for the Bcfg2 repository."""
try:
- return self.repo.revision()
+ if HAS_GITPYTHON:
+ return self.repo.head.commit.hexsha
+ else:
+ cmd = ["git", "--git-dir", self.vcs_path,
+ "--work-tree", self.vcs_root, "rev-parse", "HEAD"]
+ self.debug_log("Git: Running cmd")
+ proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
+ rv, err = proc.communicate()
+ if proc.wait():
+ raise Exception(err)
+ return rv
except:
err = sys.exc_info()[1]
- msg = "Failed to read git repository: %s" % err
+ msg = "Git: Error getting revision from %s: %s" % (self.vcs_root,
+ err)
self.logger.error(msg)
raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
@@ -144,7 +57,7 @@ class Git(Bcfg2.Server.Plugin.Version):
Update the working copy against the upstream repository
"""
try:
- self.repo.pull()
+ self.repo.git.pull("--rebase")
self.logger.info("Git repo at %s updated to %s" %
(self.vcs_root, self.get_revision()))
return True