source: tailor/vcpx/svn.py @ 14

Revision 14, 7.7 KB checked in by lele@…, 9 years ago (diff)

Preliminary bootstrap functionalities

Line 
1#! /usr/bin/python
2# -*- mode: python; coding: utf-8 -*-
3# :Progetto: vcpx -- Subversion details
4# :Creato:   ven 18 giu 2004 15:00:52 CEST
5# :Autore:   Lele Gaifax <lele@nautilus.homeip.net>
6#
7
8__docformat__ = 'reStructuredText'
9
10from cvsync.shwrap import SystemCommand
11from source import UpdatableSourceWorkingDir
12from target import SyncronizableTargetWorkingDir
13
14
15class SvnUpdate(SystemCommand):
16    COMMAND = "svn update --revision %(revision)s %(entry)s"
17
18
19class SvnInfo(SystemCommand):
20    COMMAND = "svn info %(entry)s"
21
22    def __call__(self, output=None, dry_run=False, **kwargs):
23        output = SystemCommand.__call__(self, output=True,
24                                        dry_run=dry_run,
25                                        entry=entry)
26        res = {}
27        for l in output:
28            l = l[:-1]
29            if l:
30                key, value = l.split(':', 1)
31                res[key] = value[1:]
32        return res
33
34                 
35class SvnPropGet(SystemCommand):
36    COMMAND = "svn propget %(property)s %(entry)s"
37
38   
39class SvnPropSet(SystemCommand):
40    COMMAND = "svn propset --quiet %(property)s %(value)s %(entry)s"
41
42
43class SvnLog(SystemCommand):
44    COMMAND = "svn log %(quiet)s %(xml)s --revision %(startrev)s:%(endrev)s %(entry)s"
45   
46    def __call__(self, output=None, dry_run=False, **kwargs):
47        quiet = kwargs.get('quiet', True)
48        if quiet == True:
49            kwargs['quiet'] = '--quiet'
50        elif quiet == False:
51            kwargs['quiet'] = ''
52           
53        xml = kwargs.get('xml', False)
54        if xml:
55            kwargs['xml'] = '--xml'
56            output = True
57        else:
58            kwargs['xml'] = ''
59
60        startrev = kwargs.get('startrev')
61        if not startrev:
62            kwargs['startrev'] = 'BASE'
63
64        endrev = kwargs.get('endrev')
65        if not endrev:
66            kwargs['endrev'] = 'HEAD'
67
68        output = SystemCommand.__call__(self, output=output,
69                                        dry_run=dry_run, **kwargs)
70
71        if xml:
72            # parse the output and return the result
73            pass
74
75        return output
76
77
78class SvnCheckout(SystemCommand):
79    COMMAND = "svn co --quiet --revision %(revision)s %(repository)s %(wc)s"
80
81   
82class SvnCommit(SystemCommand):
83    COMMAND = "svn commit --quiet %(logfile)s %(entries)s"
84
85    def __call__(self, output=None, dry_run=False, **kwargs):
86        logfile = kwargs.get('logfile')
87        if not logfile:
88            from tempfile import NamedTemporaryFile
89
90            log = NamedTemporaryFile(bufsize=0)
91            logmessage = kwargs.get('logmessage')
92            if logmessage:
93                print >>log, logmessage
94           
95            kwargs['logfile'] = log.name
96       
97        return SystemCommand.__call__(self, output=output,
98                                      dry_run=dry_run, **kwargs)
99
100
101class SvnAdd(SystemCommand):
102    COMMAND = "svn add --quiet --non-recursive --no-auto-props %(entry)s"
103
104
105class SvnRemove(SystemCommand):
106    COMMAND = "svn remove --quiet --force %(entry)s"
107
108
109class SvnMv(SystemCommand):
110    COMMAND = "svn mv --quiet %(old)s %(new)s"
111
112   
113class SvnCheckout(SystemCommand):
114    COMMAND = "svn co --quiet --revision %(revision)s %(repository)s %(wc)s"
115
116   
117class SvnWorkingDir(UpdatableSourceWorkingDir, SyncronizableTargetWorkingDir):
118
119    ## UpdatableSourceWorkingDir
120
121    def _getUpstreamChangesets(self, root, startfrom_rev=None):
122        svnlog = SvnLog(working_dir=root)
123        log = svnlog(quiet='--verbose', output=True, xml=True, entry='.')
124
125        return self.__parseSvnLog(log)
126
127    def __parseSvnLog(self, log):
128        """Return an object representation of the ``svn log`` thru HEAD."""
129
130        from xml.sax import parseString
131        from xml.sax.handler import ContentHandler
132
133        class SvnXMLLogHandler(ContentHandler):
134            def __init__(self):
135                self.changesets = []
136                self.current = None
137                self.current_field = []
138
139            def startElement(self, name, attributes):
140                if name == 'logentry':
141                    self.current = {}
142                    self.current['revision'] = attributes['revision']
143                    self.current['entries'] = []
144                elif name in ['author', 'date', 'msg']:
145                    self.current_field = []
146                elif name == 'path':
147                    self.current_field = []
148                    if attributes.has_key('copyfrom-path'):
149                        self.current_path_action = (
150                            attributes['action'],
151                            attributes['copyfrom-path'][1:], # make it relative
152                            attributes['copyfrom-rev'])
153                    else:
154                        self.current_path_action = attributes['action']
155
156            def endElement(self, name):
157                if name == 'logentry':
158                    # Sort the paths to make tests easier
159                    self.current['entries'].sort()
160                    self.changesets.append(ChangeSet(**self.current))
161                    self.current = None
162                elif name in ['author', 'date', 'msg']:
163                    self.current[name] = ''.join(self.current_field))
164                elif name == 'path':
165                    entry = ChangesetEntry(''.join(self.current_field)[1:])
166                    if type(self.current_path_action) == type(''):
167                        entry.action_kind = self.current_path_action
168                    else:
169                        entry.action_kind = entry.RENAMED
170                        entry.old_name = self.current_path_action[1]
171
172                    self.current['entries'].append(entry)
173
174            def characters(self, data):
175                self.current_field.append(data)
176
177       
178        handler = SvnXMLLogHandler()
179        parseString(log.getvalue(), handler)
180        return handler.changesets
181   
182    def _applyChangeset(self, root, changeset):
183        svnup = SvnUpdate(working_dir=root)
184        svnup(entry='.', revision=changeset.revision)       
185       
186    ## SyncronizableTargetWorkingDir
187
188    def _addEntry(self, root, entry):
189        """
190        Add a new entry, maybe registering the directory as well.
191        """
192
193        from os.path import split, join, exists
194
195        basedir = split(entry)[0]
196        if basedir and not exists(join(basedir, '.svn')):
197            self._addEntry(root, basedir)
198
199        c = SvnAdd(working_dir=root)
200        c(entry=entry)
201
202    def _checkoutUpstreamRevision(self, basedir, repository, module, revision):
203        """
204        Concretely do the checkout of the upstream revision.
205        """
206       
207        svnco = SvnCheckout(working_dir=basedir)
208        svnco(repository=repository, wc=module, revision=revision)
209       
210    def _commit(self, root, author, remark, changelog=None, entries=None):
211        """
212        Commit the changeset.
213        """
214
215        c = SvnCommit(working_dir=root)
216       
217        logmessage = remark + '\n'
218        if changelog:
219            logmessage = logmessage + changelog + '\n'
220           
221        if entries:
222            entries = ' '.join(entries)
223        else:
224            entries = '.'
225           
226        c(logmessage=logmessage, entries=entries)
227       
228    def _removeEntry(self, root, entry):
229        """
230        Remove an entry.
231        """
232
233        c = SvnRemove(working_dir=root)
234        c(entry=entry)
235
236    def _renameEntry(self, root, oldentry, newentry):
237        """
238        Rename an entry.
239        """
240
241        c = SvnMv(working_dir=root)
242        c(old=oldentry, new=newentry)
243
244    def _initializeWorkingDir(self, root):
245        """
246        Do whatever is needed to put the given directory under revision
247        control.
248        """
249       
250        raise "%s should override this method" % self.__class__
Note: See TracBrowser for help on using the repository browser.