From e74452aabeb77ab8ab8f50a350d77e4d9e6914a2 Mon Sep 17 00:00:00 2001 From: Mike Crute Date: Wed, 21 Apr 2010 00:16:16 -0400 Subject: Adding basic info command --- obalie/client.py | 35 ++++++++++++++++++++++++----- obalie/commands/__init__.py | 47 +++++++++++++++++++++++++++++++++++++++ obalie/commands/info.py | 54 +++++++++++++++++++++++++++++++++++++++++++++ obalie/utils.py | 10 +++++++++ 4 files changed, 140 insertions(+), 6 deletions(-) create mode 100644 obalie/commands/info.py diff --git a/obalie/client.py b/obalie/client.py index d943bb8..cc40122 100644 --- a/obalie/client.py +++ b/obalie/client.py @@ -7,6 +7,7 @@ Subversion Client @date: April 20, 2010 """ +from xml.dom import pulldom from urlparse import urlparse from obalie.commands import load_commands from obalie.exceptions import UnsupportedCommand @@ -15,6 +16,10 @@ from obalie.utils import run_command class Client(object): + """ + Subversion client that supports both remote and local subversion + repositories. + """ @inject_logger def __init__(self, repo_url, trust_server=True, config_dir=None, @@ -24,7 +29,7 @@ class Client(object): self.config_dir = config_dir self.trust_server = trust_server self.additional_config = config - self.verbosity = None + self._repository_info = None self.commands = {} self._unpack_url(repo_url) @@ -37,11 +42,17 @@ class Client(object): self.commands = load_commands() try: - cmd = self.commands[name](self) - return cmd + return self.commands[name](self) except KeyError: raise UnsupportedCommand(name) + @property + def repository_info(self): + if not self._repository_info: + self._repository_info = self.info() + + return self._repository_info + def _unpack_url(self, url): """ Parses a repository URL and loads its parts into the instance. @@ -83,10 +94,22 @@ class Client(object): return ' '.join(args) - def run_raw_command(self, subcommand, *args): - command = [self.command, self._get_svn_args(), subcommand] + def run_raw_command(self, subcommand, *args, **kwargs): + """ + Runs a raw subversion command and returns the results. + """ + cmd_args = kwargs.pop('cmd_args', '') + command = [self.command, cmd_args, self._get_svn_args(), subcommand] command = ' '.join(command + list(args)) self.logger.debug("Command: %r", command) - return run_command(command) + return run_command(command, **kwargs) + + def get_xml_output(self, subcommand, *args): + """ + Runs a raw command passing the XML flag and returns a pulldom + instance ready for use. + """ + output = self.run_raw_command(subcommand, *args, raw_output=True, cmd_args='--xml') + return pulldom.parseString(output) diff --git a/obalie/commands/__init__.py b/obalie/commands/__init__.py index e69de29..f0e3682 100644 --- a/obalie/commands/__init__.py +++ b/obalie/commands/__init__.py @@ -0,0 +1,47 @@ +# vim: set filencoding=utf8 +""" +Subversion Commands + +@author: Mike Crute (mcrute@ag.com) +@organization: SoftGroup Interactive, Inc. +@date: April 20, 2010 +""" + + +import os +import sys +from obalie.log import inject_logger + + +# Commands are relative to this directory by default +__dir__ = os.path.dirname(__file__) + + +def load_commands(from_path=__dir__, package=__name__): + commands = {} + + for filename in os.listdir(from_path): + name = filename[:-len('.py')] + import_path = '.'.join([package, name]) + + mod = __import__(import_path, globals(), locals(), [name]) + + command_catalog = getattr(mod, 'COMMANDS', None) + if command_catalog: + commands.update(command_catalog) + continue + + impl_name = "{0}Command".format(name.capitalize()) + command_impl = getattr(mod, impl_name, None) + if command_impl: + commands[name] = command_impl + + return commands + + +class BaseCommand(object): + + @inject_logger + def __init__(self, client, logger=None): + self.client = client + self.logger = logger diff --git a/obalie/commands/info.py b/obalie/commands/info.py new file mode 100644 index 0000000..5bd29fd --- /dev/null +++ b/obalie/commands/info.py @@ -0,0 +1,54 @@ +# vim: set filencoding=utf8 +""" +Subversion Info + +@author: Mike Crute (mcrute@ag.com) +@organization: SoftGroup Interactive, Inc. +@date: April 20, 2010 +""" + + +import os +from xml.dom import pulldom +from obalie.utils import join_url +from obalie.commands import BaseCommand + + +class RepositoryInfo(object): + + def __init__(self, path=None, root=None, uuid=None, revision=None): + self.path = path + self.root = root + self.uuid = uuid + self.revision = revision + + @property + def relative_path(self): + return self.path[len(self.root):] + + +class InfoCommand(BaseCommand): + + def __call__(self, path='/'): + path = join_url(self.client.repo_url, path) + self.logger.info('Running info for path: %s', path) + + repo_info = RepositoryInfo() + + xml = self.client.get_xml_output('info', path) + for event, node in xml: + if event != pulldom.START_ELEMENT: + continue + + if node.tagName in ('url', 'root', 'uuid'): + xml.expandNode(node) + + if node.tagName == 'url': + repo_info.path = node.firstChild.data + elif node.tagName == 'root': + repo_info.root = node.firstChild.data + elif node.tagName == 'uuid': + repo_info.uuid = node.firstChild.data + + return repo_info + diff --git a/obalie/utils.py b/obalie/utils.py index dcf476a..2d4be0e 100644 --- a/obalie/utils.py +++ b/obalie/utils.py @@ -9,6 +9,7 @@ Miscellaneous Utility Commands import shlex +from urlparse import urljoin from subprocess import Popen, PIPE from obalie.exceptions import ExecutableError @@ -30,3 +31,12 @@ def run_command(command, raw_output=False): return stdout else: return stdout.splitlines(True) + + +def join_url(base, path): + """ + Joins a URL but ignores the leading slash on the path that would + otherwise truncate the base part back to the hostname. + """ + path = path.lstrip('/') + return urljoin(base, path) -- cgit v1.2.3