source: tailor/vcpx/repository.py @ 788

Revision 788, 10.5 KB checked in by Todd Mokros <tmokros@…>, 8 years ago (diff)

Update git backend for external command name move

Line 
1# -*- mode: python; coding: utf-8 -*-
2# :Progetto: vcpx -- Configuration details about known repository kinds
3# :Creato:   gio 04 ago 2005 13:32:55 CEST
4# :Autore:   Lele Gaifax <lele@nautilus.homeip.net>
5# :Licenza:  GNU General Public License
6#
7
8"""
9This module holds a simple abstraction of what a repository is for
10Tailor purposes.
11"""
12
13__docformat__ = 'reStructuredText'
14
15REPO_DESCRIPTION = """\
16 Repository: %s
17       Kind: %s"""
18
19class Repository(object):
20    """
21    Collector for the configuration of a single repository.
22    """
23    METADIR = None
24    EXTRA_METADIRS = []
25    EXECUTABLE = None
26
27    def __new__(klass, name, project, which):
28        """
29        Return the right subclass for kind, if it exists.
30        """
31
32        kind = name[:name.index(':')]
33        subclass = klass
34        subclassname = kind.capitalize() + 'Repository'
35        if subclassname in globals():
36            subclass = globals()[subclassname]
37        instance = super(Repository, klass).__new__(subclass, name,
38                                                    project, which)
39        instance.kind = kind
40        return instance
41
42    def __init__(self, name, project, which):
43        """
44        Initialize a new instance of Repository, with a `name` and
45        associated to given `project`; `which` is either "source"
46        or "target".
47        """
48
49        self.name = name
50        self.project = project
51        self.which = which
52        self._load(project.config)
53        self._validateConfiguration()
54
55    def __str__(self):
56
57        s = REPO_DESCRIPTION % (self.repository, self.kind)
58        if self.module:
59            s += "\n     Module: %s" % self.module
60        return s
61
62    def _load(self, config):
63        """
64        Load the configuration for this repository.
65
66        The two main and mandatory attributes, ``repository`` and ``module``
67        can be specified either on the specific slot in the config file, or
68        as ``source-repository`` (or ``target-repository``) in its [DEFAULT]
69        section.
70
71        If the configuration does not specify a specific ``root-directory``
72        take the one from the project.
73        """
74
75        from os.path import split, expanduser
76        from sys import getdefaultencoding
77
78        self.repository = config.get(self.name, 'repository') or \
79                          config.get(self.name, '%s-repository' % self.which)
80        if self.repository:
81            self.repository = expanduser(self.repository)
82        self.module = config.get(self.name, 'module') or \
83                      config.get(self.name, '%s-module' % self.which)
84        self.rootdir = config.get(self.name, 'root-directory',
85                                  vars={'root-directory': self.project.rootdir})
86        self.subdir = config.get(self.name, 'subdir',
87                                 vars={'subdir': self.project.subdir})
88        self.encoding = config.get(self.name, 'encoding')
89        if self.encoding is None:
90            self.encoding = getdefaultencoding()
91
92    def _validateConfiguration(self):
93        """
94        Validate the configuration, possibly altering/completing it.
95        """
96
97        if self.EXECUTABLE:
98            from os import getenv
99            from os.path import isabs, exists, join
100            from vcpx.config import ConfigurationError
101
102            if isabs(self.EXECUTABLE):
103                ok = exists(self.EXECUTABLE)
104            else:
105                ok = False
106                for path in getenv('PATH').split(':'):
107                    if exists(join(path, self.EXECUTABLE)):
108                        ok = True
109                        break
110            if not ok:
111                raise ConfigurationError("The command %r used "
112                                         "by %r does not exist!" %
113                                         (self.EXECUTABLE, self.name))
114
115    def log_info(self, what):
116        """
117        Print some info on the log and, in verbose mode, to stdout as well.
118        """
119
120        self.project.log_info(what)
121
122    def log_error(self, what, exc=False):
123        """
124        Print an error message, possibly with an exception traceback,
125        to the log and to stdout as well.
126        """
127
128        self.project.log_error(what, exc)
129
130    def workingDir(self):
131        """
132        Return an instance of the specific WorkingDir for this kind of
133        repository.
134        """
135
136        from source import InvocationError
137
138        wdname = self.kind.capitalize() + 'WorkingDir'
139        modname = 'vcpx.' + self.kind
140        try:
141            wdmod = __import__(modname, globals(), locals(), [wdname])
142            workingdir = getattr(wdmod, wdname)
143        except (AttributeError, ImportError):
144            raise InvocationError("Unhandled source VCS kind: " + self.kind)
145
146        return workingdir(self)
147
148    def command(self, *args, **kwargs):
149        """
150        Return the base external command, a sequence suitable to be used
151        to init an ExternalCommand instance.
152
153        This return None if the backend uses a different way to execute
154        its actions.
155        """
156
157        executable = kwargs.get('executable', self.EXECUTABLE)
158        if executable:
159            cmd = [executable]
160            cmd.extend(args)
161            return cmd
162
163class ArxRepository(Repository):
164    METADIR = '_arx'
165
166    def _load(self, config):
167        Repository._load(self, config)
168        self.EXECUTABLE = config.get(self.name, 'arx-command', 'arx')
169
170
171class BazRepository(Repository):
172    METADIR = '{arch}'
173
174    def _load(self, config):
175        Repository._load(self, config)
176        self.EXECUTABLE = config.get(self.name, 'baz-command', 'baz')
177
178
179class BzrRepository(Repository):
180    METADIR = '.bzr'
181
182    def _load(self, config):
183        Repository._load(self, config)
184        self.EXECUTABLE = config.get(self.name, 'bzr-command', 'bzr')
185
186
187class BzrngRepository(Repository):
188    METADIR = '.bzr'
189
190    def _load(self, config):
191        Repository._load(self, config)
192        ppath = config.get(self.name, 'python-path')
193        if ppath:
194            from sys import path
195
196            if ppath not in path:
197                path.insert(0, ppath)
198
199
200class CdvRepository(Repository):
201    METADIR = '.cdv'
202
203    def _load(self, config):
204        Repository._load(self, config)
205        self.EXECUTABLE = config.get(self.name, 'cdv-command', 'cdv')
206
207
208class CgRepository(Repository):
209    METADIR = '.git'
210
211    def _load(self, config):
212        Repository._load(self, config)
213        self.EXECUTABLE = config.get(self.name, 'cg-command', 'cg')
214
215
216class CvsRepository(Repository):
217    METADIR = 'CVS'
218
219    def _load(self, config):
220        Repository._load(self, config)
221        self.EXECUTABLE = config.get(self.name, 'cvs-command', 'cvs')
222        self.tag_entries = config.get(self.name, 'tag-entries', 'True')
223
224    def _validateConfiguration(self):
225        from os.path import split
226        from config import ConfigurationError
227
228        Repository._validateConfiguration(self)
229
230        if not self.module and self.repository:
231            self.module = split(self.repository)[1]
232
233        if not self.module:
234            raise ConfigurationError("Must specify a repository and maybe "
235                                     "a module also")
236
237
238class CvspsRepository(CvsRepository):
239    def command(self, *args, **kwargs):
240        if kwargs.get('cvsps', False):
241            kwargs['executable'] = self.__cvsps
242        return CvsRepository.command(self, *args, **kwargs)
243
244    def _load(self, config):
245        CvsRepository._load(self, config)
246        self.__cvsps = config.get(self.name, 'cvsps-command', 'cvsps')
247        self.tag_entries = config.get(self.name, 'tag-entries', 'True')
248
249
250class DarcsRepository(Repository):
251    METADIR = '_darcs'
252
253    def _load(self, config):
254        Repository._load(self, config)
255        self.EXECUTABLE = config.get(self.name, 'darcs-command', 'darcs')
256
257
258class GitRepository(Repository):
259    METADIR = '.git'
260
261    def _load(self, config):
262        Repository._load(self, config)
263        self.EXECUTABLE = config.get(self.name, 'git-command', 'git')
264
265
266class HgRepository(Repository):
267    METADIR = '.hg'
268
269    def _load(self, config):
270        Repository._load(self, config)
271        self.EXECUTABLE = config.get(self.name, 'hg-command', 'hg')
272
273
274class MonotoneRepository(Repository):
275    METADIR = 'MT'
276
277    def _load(self, config):
278        Repository._load(self, config)
279        self.EXECUTABLE = config.get(self.name, 'monotone-command', 'monotone')
280        self.keyid = config.get(self.name, 'keyid')
281        self.passphrase = config.get(self.name, 'passphrase')
282        self.keyfile = config.get(self.name, 'keyfile')
283
284
285class SvnRepository(Repository):
286    METADIR = '.svn'
287
288    def command(self, *args, **kwargs):
289        if kwargs.get('svnadmin', False):
290            kwargs['executable'] = self.__svnadmin
291        return Repository.command(self, *args, **kwargs)
292
293    def _load(self, config):
294        Repository._load(self, config)
295        self.EXECUTABLE = config.get(self.name, 'svn-command', 'svn')
296        self.__svnadmin = config.get(self.name, 'svnadmin-command', 'svnadmin')
297        self.use_propset = config.get(self.name, 'use-propset', False)
298
299    def _validateConfiguration(self):
300        from vcpx.config import ConfigurationError
301
302        Repository._validateConfiguration(self)
303
304        if not self.repository:
305            raise ConfigurationError("Must specify the root of the "
306                                     "Subversion repository used "
307                                     "as %s with the option "
308                                     "'repository'" % self.which)
309
310        if not self.module:
311            raise ConfigurationError("Must specify the path within the "
312                                     "Subversion repository as 'module'")
313
314        if not self.module.startswith('/'):
315            self.project.log_info("Prepending '/' to module")
316            self.module = '/' + self.module
317
318    def workingDir(self):
319        wd = Repository.workingDir(self)
320        wd.USE_PROPSET = self.use_propset
321        return wd
322
323
324class SvndumpRepository(Repository):
325
326    def _validateConfiguration(self):
327        Repository._validateConfiguration(self)
328
329        if self.module and self.module.startswith('/'):
330            self.project.log_info("Removing starting '/' from module")
331            self.module = self.module[1:]
332        if self.module and not self.module.endswith('/'):
333            self.module = self.module+'/'
334
335class TlaRepository(Repository):
336    METADIR = '{arch}'
337
338    def _load(self, config):
339        Repository._load(self, config)
340        self.EXECUTABLE = config.get(self.name, 'tla-command', 'tla')
341        self.IGNORE_IDS = config.get(self.name, 'ignore-ids', False)
342        if self.IGNORE_IDS:
343            self.EXTRA_METADIRS = ['.arch-ids']
Note: See TracBrowser for help on using the repository browser.