# vim: set filencoding=utf8 """ Subversion Client @author: Mike Crute (mcrute@gmail.com) @organization: SoftGroup Interactive, Inc. @date: April 20, 2010 """ from xml.dom import pulldom from urlparse import urlparse from obalie.commands import load_commands from obalie.exceptions import UnsupportedCommand from obalie.log import inject_logger 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, svn_command='svn', logger=None, **config): self.logger = logger self.command = svn_command self.config_dir = config_dir self.trust_server = trust_server self.additional_config = config self._repository_info = None self.commands = {} self._unpack_url(repo_url) def __getattr__(self, name): """ Proxy commands through to a command object. """ if not self.commands: self.commands = load_commands() try: 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. """ parsed = urlparse(url) self.repo_url = "{0}://{1}".format(parsed.scheme, parsed.hostname) if parsed.port: self.repo_url += ":{0}".format(parsed.port) self.repo_url += parsed.path self.logger.debug('Repository URL: %r', self.repo_url) self.username = parsed.username self.password = parsed.password def _get_svn_args(self): """ Gets a string of global options for the subversion command. """ args = [] if self.username: args.append('--username={0}'.format(self.username)) if self.password: args.append('--password={0}'.format(self.password)) args.append('--no-auth-cache') if self.config_dir: args.append('--config-dir={0}'.format(self.config_dir)) if self.trust_server: args.append('--trust-server-cert') args.append('--non-interactive') for key, value in self.additional_config.items(): option = '{0}={1}'.format(key, value) args.append('--config-option={0}'.format(option)) return ' '.join(args) 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, **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)