summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2012-11-15 17:03:23 -0500
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2012-11-16 09:57:53 -0500
commit12684bada59c9ddc08165dad757682514b54634c (patch)
tree17fcba524c1ce6f157a3c93e3a9a77b5d1fa9d6f
parenta6a29aa01744cc893741ddf558f415b7c705d3f6 (diff)
downloadbcfg2-12684bada59c9ddc08165dad757682514b54634c.tar.gz
bcfg2-12684bada59c9ddc08165dad757682514b54634c.tar.bz2
bcfg2-12684bada59c9ddc08165dad757682514b54634c.zip
Git: Added ability to update to a specific tree-ish
-rw-r--r--doc/server/plugins/version/git.txt35
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Git.py51
2 files changed, 73 insertions, 13 deletions
diff --git a/doc/server/plugins/version/git.txt b/doc/server/plugins/version/git.txt
index b3c469d6c..3f7ab9d9b 100644
--- a/doc/server/plugins/version/git.txt
+++ b/doc/server/plugins/version/git.txt
@@ -20,9 +20,38 @@ it will include the current repository revision in the
reports/statistics.
Additionally, if the ``GitPython`` library is installed, the Git
-plugin exposes an additional XML-RPC method call, ``Git.Update``,
-which updates the working copy to the latest version in the remote
-origin.
+plugin exposes an additional XML-RPC method call, ``Git.Update``.
+With no arguments, ``Git.Update`` updates the working copy to the
+latest version in the remote tracking branch. If the current working
+copy doesn't have a remote tracking branch, then nothing is done.
+
+``Git.Update`` can also be given a single argument, the name of a git
+tree-ish (branch, tag, ref, commit, etc.) to check out. When this is
+done, the new working is updated as well.
+
+For example::
+
+ bcfg2-admin xcmd Git.Update master
+
+This checks out the ``master`` branch and updates it to the latest
+data from the remote ``master`` (if applicable). If you then run::
+
+ bcfg2-admin xcmd Git.Update
+
+This updates to the latest remote data without changing branches.
+Then::
+
+ bcfg2-admin xcmd Git.Update dd0bb776c
+
+This checks out the specified commit. Subsequently::
+
+ bcfg2-admin xcmd Git.Update
+
+This does nothing, because the working copy is now in "detached HEAD"
+state, and there can be no remote tracking branch to update from.
+
+To put it another way, once you tell ``Git.Update`` which tree-ish to
+checkout, it stays on that tree-ish until you tell it otherwise.
Enabling the Git plugin
=======================
diff --git a/src/lib/Bcfg2/Server/Plugins/Git.py b/src/lib/Bcfg2/Server/Plugins/Git.py
index 61d581009..8cc63a46f 100644
--- a/src/lib/Bcfg2/Server/Plugins/Git.py
+++ b/src/lib/Bcfg2/Server/Plugins/Git.py
@@ -52,17 +52,48 @@ class Git(Bcfg2.Server.Plugin.Version):
self.logger.error(msg)
raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
- def Update(self):
+ def Update(self, ref=None):
""" Git.Update() => True|False
Update the working copy against the upstream repository
"""
+ self.logger.info("Git: Git.Update(ref='%s')" % ref)
+ self.debug_log("Git: Performing garbage collection on repo at %s" %
+ self.vcs_root)
try:
- self.repo.git.pull("--rebase")
- self.logger.info("Git repo at %s updated to %s" %
- (self.vcs_root, self.get_revision()))
- return True
- except: # pylint: disable=W0702
- err = sys.exc_info()[1]
- msg = "Failed to pull from git repository: %s" % err
- self.logger.error(msg)
- raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+ self.repo.git.gc('--auto')
+ except git.GitCommandError:
+ self.logger.warning("Git: Failed to perform garbage collection: %s"
+ % sys.exc_info()[1])
+
+ if ref:
+ self.debug_log("Git: Checking out %s" % ref)
+ try:
+ self.repo.git.checkout('-f', ref)
+ except git.GitCommandError:
+ err = sys.exc_info()[1]
+ msg = "Git: Failed to checkout %s: %s" % (ref, err)
+ self.logger.error(msg)
+ raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+
+ # determine if we should try to pull to get the latest commit
+ # on this head
+ tracking = None
+ if not self.repo.head.is_detached:
+ self.debug_log("Git: Determining if %s is a tracking branch" %
+ self.repo.head.ref.name)
+ tracking = self.repo.head.ref.tracking_branch()
+
+ if tracking is not None:
+ self.debug_log("Git: %s is a tracking branch, pulling from %s" %
+ (self.repo.head.ref.name, tracking))
+ try:
+ self.repo.git.pull("--rebase")
+ except: # pylint: disable=W0702
+ err = sys.exc_info()[1]
+ msg = "Git: Failed to pull from upstream: %s" % err
+ self.logger.error(msg)
+ raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+
+ self.logger.info("Git: Repo at %s updated to %s" %
+ (self.vcs_root, self.get_revision()))
+ return True