summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2012-10-18 11:33:38 -0400
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2012-10-30 09:11:53 -0400
commit63a5b62dba190007634e1e0f2f834057b63aeafd (patch)
treebeb6d51675d43fe8303aff62a3c9272e82e67520 /src/lib
parent7b9987d1835ff422e21f0b2f36c93d956192bf4b (diff)
downloadbcfg2-63a5b62dba190007634e1e0f2f834057b63aeafd.tar.gz
bcfg2-63a5b62dba190007634e1e0f2f834057b63aeafd.tar.bz2
bcfg2-63a5b62dba190007634e1e0f2f834057b63aeafd.zip
added Git.Update RMI, ability to base bcfg2 VCS repo at a different directory than the repo root
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/Bcfg2/Options.py8
-rw-r--r--src/lib/Bcfg2/Server/Plugin/interfaces.py27
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Bzr.py10
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Cvs.py15
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Darcs.py12
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Fossil.py10
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Git.py143
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Hg.py13
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Svn.py133
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Svn2.py116
10 files changed, 286 insertions, 201 deletions
diff --git a/src/lib/Bcfg2/Options.py b/src/lib/Bcfg2/Options.py
index 83234a792..f3765a5ec 100644
--- a/src/lib/Bcfg2/Options.py
+++ b/src/lib/Bcfg2/Options.py
@@ -572,6 +572,11 @@ SERVER_DAEMON_GROUP = \
default=0,
cf=('server', 'group'),
cook=get_gid)
+SERVER_VCS_ROOT = \
+ Option('Server VCS repository root',
+ default=None,
+ odesc='<VCS repository root>',
+ cf=('server', 'vcs_root'))
# database options
DB_ENGINE = \
@@ -1078,7 +1083,8 @@ SERVER_COMMON_OPTIONS = dict(repo=SERVER_REPOSITORY,
ca=SERVER_CA,
protocol=SERVER_PROTOCOL,
web_configfile=WEB_CFILE,
- backend=SERVER_BACKEND)
+ backend=SERVER_BACKEND,
+ vcs_root=SERVER_VCS_ROOT)
CRYPT_OPTIONS = dict(encrypt=ENCRYPT,
decrypt=DECRYPT,
diff --git a/src/lib/Bcfg2/Server/Plugin/interfaces.py b/src/lib/Bcfg2/Server/Plugin/interfaces.py
index 894165858..cba3e8145 100644
--- a/src/lib/Bcfg2/Server/Plugin/interfaces.py
+++ b/src/lib/Bcfg2/Server/Plugin/interfaces.py
@@ -506,7 +506,7 @@ class GoalValidator(object):
raise NotImplementedError
-class Version(object):
+class Version(Plugin):
""" Version plugins interact with various version control systems. """
#: The path to the VCS metadata file or directory, relative to the
@@ -514,26 +514,23 @@ class Version(object):
#: be ".svn"
__vcs_metadata_path__ = None
- def __init__(self, datastore):
- """
- :param datastore: The path to the Bcfg2 repository on the
- filesystem
- :type datastore: string
- :raises: :class:`Bcfg2.Server.Plugin.exceptions.PluginInitError`
-
- .. autoattribute:: __vcs_metadata_path__
- """
+ def __init__(self, core, datastore):
+ Plugin.__init__(self, core, datastore)
- self.datastore = datastore
if self.__vcs_metadata_path__:
- self.vcs_path = os.path.join(datastore, self.__vcs_metadata_path__)
-
- if os.path.exists(self.vcs_path):
- self.get_revision()
+ if core.setup['vcs_root']:
+ self.vcs_root = core.setup['vcs_root']
else:
+ self.vcs_root = datastore
+ self.vcs_path = os.path.join(self.vcs_root,
+ self.__vcs_metadata_path__)
+
+ if not os.path.exists(self.vcs_path):
raise PluginInitError("%s is not present" % self.vcs_path)
else:
self.vcs_path = None
+ __init__.__doc__ = Plugin.__init__.__doc__ + """
+.. autoattribute:: __vcs_metadata_path__ """
def get_revision(self):
""" Return the current revision of the Bcfg2 specification.
diff --git a/src/lib/Bcfg2/Server/Plugins/Bzr.py b/src/lib/Bcfg2/Server/Plugins/Bzr.py
index a8b4113ff..e0cbdf72a 100644
--- a/src/lib/Bcfg2/Server/Plugins/Bzr.py
+++ b/src/lib/Bcfg2/Server/Plugins/Bzr.py
@@ -6,23 +6,21 @@ from bzrlib.workingtree import WorkingTree
from bzrlib import errors
-class Bzr(Bcfg2.Server.Plugin.Plugin,
- Bcfg2.Server.Plugin.Version):
+class Bzr(Bcfg2.Server.Plugin.Version):
""" The Bzr plugin provides a revision interface for Bcfg2 repos
using bazaar. """
__author__ = 'bcfg-dev@mcs.anl.gov'
def __init__(self, core, datastore):
- Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore)
- Bcfg2.Server.Plugin.Version.__init__(self, datastore)
+ Bcfg2.Server.Plugin.Version.__init__(self, core, datastore)
self.logger.debug("Initialized Bazaar plugin with directory %s at "
- "revision = %s" % (self.datastore,
+ "revision = %s" % (self.vcs_root,
self.get_revision()))
def get_revision(self):
"""Read Bazaar revision information for the Bcfg2 repository."""
try:
- working_tree = WorkingTree.open(self.datastore)
+ working_tree = WorkingTree.open(self.vcs_root)
revision = str(working_tree.branch.revno())
if (working_tree.has_changes(working_tree.basis_tree()) or
working_tree.unknowns()):
diff --git a/src/lib/Bcfg2/Server/Plugins/Cvs.py b/src/lib/Bcfg2/Server/Plugins/Cvs.py
index a36a116f5..ba1559a1a 100644
--- a/src/lib/Bcfg2/Server/Plugins/Cvs.py
+++ b/src/lib/Bcfg2/Server/Plugins/Cvs.py
@@ -5,17 +5,15 @@ from subprocess import Popen, PIPE
import Bcfg2.Server.Plugin
-class Cvs(Bcfg2.Server.Plugin.Plugin,
- Bcfg2.Server.Plugin.Version):
+class Cvs(Bcfg2.Server.Plugin.Version):
""" The Cvs plugin provides a revision interface for Bcfg2 repos
using cvs."""
__author__ = 'bcfg-dev@mcs.anl.gov'
__vcs_metadata_path__ = "CVSROOT"
def __init__(self, core, datastore):
- Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore)
- Bcfg2.Server.Plugin.Version.__init__(self, datastore)
- self.logger.debug("Initialized cvs plugin with cvs directory %s" %
+ Bcfg2.Server.Plugin.Version.__init__(self, core, datastore)
+ self.logger.debug("Initialized cvs plugin with CVS directory %s" %
self.vcs_path)
def get_revision(self):
@@ -23,11 +21,12 @@ class Cvs(Bcfg2.Server.Plugin.Plugin,
try:
data = Popen("env LC_ALL=C cvs log",
shell=True,
- cwd=self.datastore,
+ cwd=self.vcs_root,
stdout=PIPE).stdout.readlines()
return data[3].strip('\n')
except IndexError:
- msg = "Failed to read cvs log"
+ msg = "Failed to read CVS log"
self.logger.error(msg)
- self.logger.error('Ran command "cvs log %s"' % self.datastore)
+ self.logger.error('Ran command "cvs log" from directory %s' %
+ self.vcs_root)
raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
diff --git a/src/lib/Bcfg2/Server/Plugins/Darcs.py b/src/lib/Bcfg2/Server/Plugins/Darcs.py
index 9ec8e2df3..0033e00f3 100644
--- a/src/lib/Bcfg2/Server/Plugins/Darcs.py
+++ b/src/lib/Bcfg2/Server/Plugins/Darcs.py
@@ -5,16 +5,14 @@ from subprocess import Popen, PIPE
import Bcfg2.Server.Plugin
-class Darcs(Bcfg2.Server.Plugin.Plugin,
- Bcfg2.Server.Plugin.Version):
+class Darcs(Bcfg2.Server.Plugin.Version):
""" Darcs is a version plugin for dealing with Bcfg2 repos stored
in the Darcs VCS. """
__author__ = 'bcfg-dev@mcs.anl.gov'
__vcs_metadata_path__ = "_darcs"
def __init__(self, core, datastore):
- Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore)
- Bcfg2.Server.Plugin.Version.__init__(self, datastore)
+ Bcfg2.Server.Plugin.Version.__init__(self, core, datastore)
self.logger.debug("Initialized Darcs plugin with darcs directory %s" %
self.vcs_path)
@@ -23,13 +21,13 @@ class Darcs(Bcfg2.Server.Plugin.Plugin,
try:
data = Popen("env LC_ALL=C darcs changes",
shell=True,
- cwd=self.datastore,
+ cwd=self.vcs_root,
stdout=PIPE).stdout.readlines()
revision = data[0].strip('\n')
except:
msg = "Failed to read darcs repository"
self.logger.error(msg)
- self.logger.error('Ran command "darcs changes" from directory "%s"'
- % self.datastore)
+ self.logger.error('Ran command "darcs changes" from directory %s' %
+ self.vcs_root)
raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
return revision
diff --git a/src/lib/Bcfg2/Server/Plugins/Fossil.py b/src/lib/Bcfg2/Server/Plugins/Fossil.py
index 85d0f38f5..f6735df12 100644
--- a/src/lib/Bcfg2/Server/Plugins/Fossil.py
+++ b/src/lib/Bcfg2/Server/Plugins/Fossil.py
@@ -5,16 +5,14 @@ from subprocess import Popen, PIPE
import Bcfg2.Server.Plugin
-class Fossil(Bcfg2.Server.Plugin.Plugin,
- Bcfg2.Server.Plugin.Version):
+class Fossil(Bcfg2.Server.Plugin.Version):
""" The Fossil plugin provides a revision interface for Bcfg2
repos using fossil. """
__author__ = 'bcfg-dev@mcs.anl.gov'
__vcs_metadata_path__ = "_FOSSIL_"
def __init__(self, core, datastore):
- Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore)
- Bcfg2.Server.Plugin.Version.__init__(self, datastore)
+ Bcfg2.Server.Plugin.Version.__init__(self, core, datastore)
self.logger.debug("Initialized Fossil plugin with fossil directory %s"
% self.vcs_path)
@@ -23,7 +21,7 @@ class Fossil(Bcfg2.Server.Plugin.Plugin,
try:
data = Popen("env LC_ALL=C fossil info",
shell=True,
- cwd=self.datastore,
+ cwd=self.vcs_root,
stdout=PIPE).stdout.readlines()
revline = [line.split(': ')[1].strip() for line in data if \
line.split(': ')[0].strip() == 'checkout'][-1]
@@ -32,5 +30,5 @@ class Fossil(Bcfg2.Server.Plugin.Plugin,
msg = "Failed to read fossil info"
self.logger.error(msg)
self.logger.error('Ran command "fossil info" from directory "%s"' %
- self.datastore)
+ self.vcs_root)
raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
diff --git a/src/lib/Bcfg2/Server/Plugins/Git.py b/src/lib/Bcfg2/Server/Plugins/Git.py
index 177770a12..b7269af48 100644
--- a/src/lib/Bcfg2/Server/Plugins/Git.py
+++ b/src/lib/Bcfg2/Server/Plugins/Git.py
@@ -1,38 +1,153 @@
""" 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
+
+
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)
+
except ImportError:
- # fallback to shell commands when dulwich unavailable
- from subprocess import Popen, PIPE
+ try:
+ import git
-import Bcfg2.Server.Plugin
+ 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
-class Git(Bcfg2.Server.Plugin.Plugin,
- Bcfg2.Server.Plugin.Version):
+ 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", self.path,
+ "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", self.path,
+ "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")
+
+
+class Git(Bcfg2.Server.Plugin.Version):
""" The Git plugin provides a revision interface for Bcfg2 repos
using git. """
__author__ = 'bcfg-dev@mcs.anl.gov'
__vcs_metadata_path__ = ".git"
+ __rmi__ = Bcfg2.Server.Plugin.Version.__rmi__ + ['Update']
def __init__(self, core, datastore):
- Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore)
- Bcfg2.Server.Plugin.Version.__init__(self, datastore)
+ Bcfg2.Server.Plugin.Version.__init__(self, core, datastore)
+ self.repo = GitAPI(self.vcs_root)
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 Repo(self.datastore).head()
- except NameError:
- return Popen("env LC_ALL=C git log -1 --pretty=format:%H",
- shell=True,
- cwd=self.datastore,
- stdout=PIPE).stdout.readline()
+ return self.repo.revision()
except:
- msg = "Failed to read git repository"
+ err = sys.exc_info()[1]
+ msg = "Failed to read git repository: %s" % err
+ self.logger.error(msg)
+ raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+
+ def Update(self):
+ """ Git.Update() => True|False
+ Update the working copy against the upstream repository
+ """
+ try:
+ self.repo.pull()
+ 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)
diff --git a/src/lib/Bcfg2/Server/Plugins/Hg.py b/src/lib/Bcfg2/Server/Plugins/Hg.py
index b5dec2e3f..3fd3918bd 100644
--- a/src/lib/Bcfg2/Server/Plugins/Hg.py
+++ b/src/lib/Bcfg2/Server/Plugins/Hg.py
@@ -1,32 +1,31 @@
""" The Hg plugin provides a revision interface for Bcfg2 repos using
mercurial. """
+import sys
from mercurial import ui, hg
import Bcfg2.Server.Plugin
-class Hg(Bcfg2.Server.Plugin.Plugin,
- Bcfg2.Server.Plugin.Version):
+class Hg(Bcfg2.Server.Plugin.Version):
""" The Hg plugin provides a revision interface for Bcfg2 repos
using mercurial. """
-
__author__ = 'bcfg-dev@mcs.anl.gov'
__vcs_metadata_path__ = ".hg"
def __init__(self, core, datastore):
- Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore)
- Bcfg2.Server.Plugin.Version.__init__(self, datastore)
+ Bcfg2.Server.Plugin.Version.__init__(self, core, datastore)
self.logger.debug("Initialized hg plugin with hg directory %s" %
self.vcs_path)
def get_revision(self):
"""Read hg revision information for the Bcfg2 repository."""
try:
- repo_path = self.datastore + "/"
+ repo_path = self.vcs_root + "/"
repo = hg.repository(ui.ui(), repo_path)
tip = repo.changelog.tip()
return repo.changelog.rev(tip)
except:
- msg = "Failed to read hg repository"
+ err = sys.exc_info()[1]
+ msg = "Failed to read hg repository: %s" % err
self.logger.error(msg)
raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
diff --git a/src/lib/Bcfg2/Server/Plugins/Svn.py b/src/lib/Bcfg2/Server/Plugins/Svn.py
index 5bc9d6bbd..fda6b57b5 100644
--- a/src/lib/Bcfg2/Server/Plugins/Svn.py
+++ b/src/lib/Bcfg2/Server/Plugins/Svn.py
@@ -1,34 +1,125 @@
""" The Svn plugin provides a revision interface for Bcfg2 repos using
-svn. """
+Subversion. If PySvn libraries are installed, then it exposes two
+additional XML-RPC methods for committing data to the repository and
+updating the repository. """
-import pipes
-from subprocess import Popen, PIPE
+import sys
import Bcfg2.Server.Plugin
+try:
+ import pysvn
+ HAS_SVN = True
+except ImportError:
+ import pipes
+ from subprocess import Popen, PIPE
+ HAS_SVN = False
-class Svn(Bcfg2.Server.Plugin.Plugin,
- Bcfg2.Server.Plugin.Version):
- """ The Svn plugin provides a revision interface for Bcfg2 repos
- using svn. """
+class Svn(Bcfg2.Server.Plugin.Version):
+ """Svn is a version plugin for dealing with Bcfg2 repos."""
__author__ = 'bcfg-dev@mcs.anl.gov'
- __vcs_metadata_path__ = ".svn"
+ if HAS_SVN:
+ __rmi__ = Bcfg2.Server.Plugin.Version.__rmi__ + ['Update', 'Commit']
+ else:
+ __vcs_metadata_path__ = ".svn"
def __init__(self, core, datastore):
- Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore)
- Bcfg2.Server.Plugin.Version.__init__(self, datastore)
- self.logger.debug("Initialized svn plugin with svn directory %s" %
+ Bcfg2.Server.Plugin.Version.__init__(self, core, datastore)
+
+ self.revision = None
+ self.svn_root = None
+ if not HAS_SVN:
+ self.logger.debug("Svn: PySvn not found, using CLI interface to "
+ "SVN")
+ self.client = None
+ else:
+ self.client = pysvn.Client()
+
+ self.logger.debug("Initialized svn plugin with SVN directory %s" %
self.vcs_path)
def get_revision(self):
"""Read svn revision information for the Bcfg2 repository."""
+ msg = None
+ if HAS_SVN:
+ try:
+ info = self.client.info(self.vcs_root)
+ self.revision = info.revision
+ self.svn_root = info.url
+ return str(self.revision.number)
+ except pysvn.ClientError: # pylint: disable=E1101
+ msg = "Svn: Failed to get revision: %s" % sys.exc_info()[1]
+ else:
+ try:
+ data = Popen(("env LC_ALL=C svn info %s" %
+ pipes.quote(self.vcs_root)), shell=True,
+ stdout=PIPE).communicate()[0].split('\n')
+ return [line.split(': ')[1] for line in data \
+ if line[:9] == 'Revision:'][-1]
+ except IndexError:
+ msg = "Failed to read svn info"
+ self.logger.error('Ran command "svn info %s"' % self.vcs_root)
+ self.revision = None
+ self.logger.error(msg)
+ raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+
+ def Update(self):
+ '''Svn.Update() => True|False\nUpdate svn working copy\n'''
try:
- data = Popen(("env LC_ALL=C svn info %s" %
- pipes.quote(self.datastore)), shell=True,
- stdout=PIPE).communicate()[0].split('\n')
- return [line.split(': ')[1] for line in data \
- if line[:9] == 'Revision:'][-1]
- except IndexError:
- msg = "Failed to read svn info"
- self.logger.error(msg)
- self.logger.error('Ran command "svn info %s"' % self.datastore)
- raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+ old_revision = self.revision.number
+ self.revision = self.client.update(self.vcs_root, recurse=True)[0]
+ except pysvn.ClientError: # pylint: disable=E1101
+ err = sys.exc_info()[1]
+ # try to be smart about the error we got back
+ details = None
+ if "callback_ssl_server_trust_prompt" in str(err):
+ details = "SVN server certificate is not trusted"
+ elif "callback_get_login" in str(err):
+ details = "SVN credentials not cached"
+
+ if details is None:
+ self.logger.error("Svn: Failed to update server repository",
+ exc_info=1)
+ else:
+ self.logger.error("Svn: Failed to update server repository: "
+ "%s" % details)
+ return False
+
+ if old_revision == self.revision.number:
+ self.logger.debug("repository is current")
+ else:
+ self.logger.info("Updated %s from revision %s to %s" % \
+ (self.vcs_root, old_revision, self.revision.number))
+ return True
+
+ def Commit(self):
+ """Svn.Commit() => True|False\nCommit svn repository\n"""
+ # First try to update
+ if not self.Update():
+ self.logger.error("Failed to update svn repository, refusing to "
+ "commit changes")
+ return False
+
+ try:
+ self.revision = self.client.checkin([self.vcs_root],
+ 'Svn: autocommit',
+ recurse=True)
+ self.revision = self.client.update(self.vcs_root, recurse=True)[0]
+ self.logger.info("Svn: Commited changes. At %s" %
+ self.revision.number)
+ return True
+ except pysvn.ClientError: # pylint: disable=E1101
+ err = sys.exc_info()[1]
+ # try to be smart about the error we got back
+ details = None
+ if "callback_ssl_server_trust_prompt" in str(err):
+ details = "SVN server certificate is not trusted"
+ elif "callback_get_login" in str(err):
+ details = "SVN credentials not cached"
+
+ if details is None:
+ self.logger.error("Svn: Failed to commit changes",
+ exc_info=1)
+ else:
+ self.logger.error("Svn: Failed to commit changes: %s" %
+ details)
+ return False
diff --git a/src/lib/Bcfg2/Server/Plugins/Svn2.py b/src/lib/Bcfg2/Server/Plugins/Svn2.py
deleted file mode 100644
index 19093eb6a..000000000
--- a/src/lib/Bcfg2/Server/Plugins/Svn2.py
+++ /dev/null
@@ -1,116 +0,0 @@
-""" The Svn2 plugin provides a revision interface for Bcfg2 repos using
-Subversion. It uses a pure python backend and exposes two additional
-XML-RPC methods. """
-
-import sys
-import Bcfg2.Server.Plugin
-try:
- import pysvn
- HAS_SVN = False
-except ImportError:
- HAS_SVN = True
-
-
-class Svn2(Bcfg2.Server.Plugin.Plugin,
- Bcfg2.Server.Plugin.Version):
- """Svn is a version plugin for dealing with Bcfg2 repos."""
- __author__ = 'bcfg-dev@mcs.anl.gov'
-
- conflicts = ['Svn']
- __rmi__ = Bcfg2.Server.Plugin.Plugin.__rmi__ + ['Update', 'Commit']
-
- def __init__(self, core, datastore):
- Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore)
- Bcfg2.Server.Plugin.Version.__init__(self, datastore)
-
- if HAS_SVN:
- msg = "Missing PySvn"
- self.logger.error("Svn2: " + msg)
- raise Bcfg2.Server.Plugin.PluginInitError(msg)
-
- self.client = pysvn.Client()
-
- self.svn_root = None
- self.revision = None
-
- # Read revision from bcfg2 repo
- revision = self.get_revision()
- if not self.revision:
- raise Bcfg2.Server.Plugin.PluginInitError("Failed to get revision")
-
- self.logger.debug("Initialized svn plugin with svn root %s at "
- "revision %s" % (self.svn_root, revision))
-
- def get_revision(self):
- """Read svn revision information for the Bcfg2 repository."""
- try:
- info = self.client.info(self.datastore)
- self.revision = info.revision
- self.svn_root = info.url
- return str(self.revision.number)
- except pysvn.ClientError: # pylint: disable=E1101
- self.logger.error("Svn2: Failed to get revision", exc_info=1)
- self.revision = None
- return str(-1)
-
- def Update(self):
- '''Svn2.Update() => True|False\nUpdate svn working copy\n'''
- try:
- old_revision = self.revision.number
- self.revision = self.client.update(self.datastore, recurse=True)[0]
- except pysvn.ClientError: # pylint: disable=E1101
- err = sys.exc_info()[1]
- # try to be smart about the error we got back
- details = None
- if "callback_ssl_server_trust_prompt" in str(err):
- details = "SVN server certificate is not trusted"
- elif "callback_get_login" in str(err):
- details = "SVN credentials not cached"
-
- if details is None:
- self.logger.error("Svn2: Failed to update server repository",
- exc_info=1)
- else:
- self.logger.error("Svn2: Failed to update server repository: "
- "%s" % details)
- return False
-
- if old_revision == self.revision.number:
- self.logger.debug("repository is current")
- else:
- self.logger.info("Updated %s from revision %s to %s" % \
- (self.datastore, old_revision, self.revision.number))
- return True
-
- def Commit(self):
- """Svn2.Commit() => True|False\nCommit svn repository\n"""
- # First try to update
- if not self.Update():
- self.logger.error("Failed to update svn repository, refusing to "
- "commit changes")
- return False
-
- try:
- self.revision = self.client.checkin([self.datastore],
- 'Svn2: autocommit',
- recurse=True)
- self.revision = self.client.update(self.datastore, recurse=True)[0]
- self.logger.info("Svn2: Commited changes. At %s" %
- self.revision.number)
- return True
- except pysvn.ClientError: # pylint: disable=E1101
- err = sys.exc_info()[1]
- # try to be smart about the error we got back
- details = None
- if "callback_ssl_server_trust_prompt" in str(err):
- details = "SVN server certificate is not trusted"
- elif "callback_get_login" in str(err):
- details = "SVN credentials not cached"
-
- if details is None:
- self.logger.error("Svn2: Failed to commit changes",
- exc_info=1)
- else:
- self.logger.error("Svn2: Failed to commit changes: %s" %
- details)
- return False