summaryrefslogtreecommitdiff
path: root/obalie/client.py
blob: cc40122494e3cfad0f15ff524e654223e57cbe75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# vim: set filencoding=utf8
"""
Subversion Client

@author: Mike Crute (mcrute@ag.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)