source: tailor/vcpx/svn.py @ 36

Revision 36, 8.3 KB checked in by lele@…, 9 years ago (diff)

Show the dots while checking out

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"""
9This module contains supporting classes for Subversion.
10"""
11
12__docformat__ = 'reStructuredText'
13
14from shwrap import SystemCommand
15from source import UpdatableSourceWorkingDir
16from target import SyncronizableTargetWorkingDir
17
18
19class SvnUpdate(SystemCommand):
20    COMMAND = "svn update --revision %(revision)s %(entry)s"
21
22
23class SvnInfo(SystemCommand):
24    COMMAND = "LANG= svn info %(entry)s"
25
26    def __call__(self, output=None, dry_run=False, **kwargs):
27        output = SystemCommand.__call__(self, output=True,
28                                        dry_run=dry_run,
29                                        **kwargs)
30        res = {}
31        for l in output:
32            l = l[:-1]
33            if l:
34                key, value = l.split(':', 1)
35                res[key] = value[1:]
36        return res
37
38                 
39class SvnPropGet(SystemCommand):
40    COMMAND = "svn propget %(property)s %(entry)s"
41
42   
43class SvnPropSet(SystemCommand):
44    COMMAND = "svn propset --quiet %(property)s %(value)s %(entry)s"
45
46
47class SvnLog(SystemCommand):
48    COMMAND = "svn log %(quiet)s %(xml)s --revision %(startrev)s:%(endrev)s %(entry)s"
49   
50    def __call__(self, output=None, dry_run=False, **kwargs):
51        quiet = kwargs.get('quiet', True)
52        if quiet == True:
53            kwargs['quiet'] = '--quiet'
54        elif quiet == False:
55            kwargs['quiet'] = ''
56           
57        xml = kwargs.get('xml', False)
58        if xml:
59            kwargs['xml'] = '--xml'
60            output = True
61        else:
62            kwargs['xml'] = ''
63
64        startrev = kwargs.get('startrev')
65        if not startrev:
66            kwargs['startrev'] = 'BASE'
67
68        endrev = kwargs.get('endrev')
69        if not endrev:
70            kwargs['endrev'] = 'HEAD'
71
72        output = SystemCommand.__call__(self, output=output,
73                                        dry_run=dry_run, **kwargs)
74
75        if xml:
76            # parse the output and return the result
77            pass
78
79        return output
80
81
82class SvnCommit(SystemCommand):
83    COMMAND = "svn commit --file %(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 --no-auto-props --non-recursive %(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 --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        actualrev = SvnInfo(working_dir=root)(entry='.')['Revision']
123        svnlog = SvnLog(working_dir=root)
124        log = svnlog(quiet='--verbose', output=True, xml=True,
125                     startrev=int(actualrev)+1, entry='.')
126
127        return self.__parseSvnLog(log)
128
129    def __parseSvnLog(self, log):
130        """Return an object representation of the ``svn log`` thru HEAD."""
131
132        from xml.sax import parseString
133        from xml.sax.handler import ContentHandler
134        from changes import ChangesetEntry, Changeset
135       
136        class SvnXMLLogHandler(ContentHandler):
137            def __init__(self):
138                self.changesets = []
139                self.current = None
140                self.current_field = []
141
142            def startElement(self, name, attributes):
143                if name == 'logentry':
144                    self.current = {}
145                    self.current['revision'] = attributes['revision']
146                    self.current['entries'] = []
147                elif name in ['author', 'date', 'msg']:
148                    self.current_field = []
149                elif name == 'path':
150                    self.current_field = []
151                    if attributes.has_key('copyfrom-path'):
152                        self.current_path_action = (
153                            attributes['action'],
154                            attributes['copyfrom-path'][1:], # make it relative
155                            attributes['copyfrom-rev'])
156                    else:
157                        self.current_path_action = attributes['action']
158
159            def endElement(self, name):
160                if name == 'logentry':
161                    # Sort the paths to make tests easier
162                    self.current['entries'].sort()
163                    self.changesets.append(Changeset(self.current['revision'],
164                                                     self.current['date'],
165                                                     self.current['author'],
166                                                     self.current['msg'],
167                                                     self.current['entries']))
168                    self.current = None
169                elif name in ['author', 'date', 'msg']:
170                    self.current[name] = ''.join(self.current_field)
171                elif name == 'path':
172                    entry = ChangesetEntry(''.join(self.current_field)[1:])
173                    if type(self.current_path_action) == type( () ):
174                        entry.action_kind = entry.RENAMED
175                        entry.old_name = self.current_path_action[1]
176                    else:
177                        entry.action_kind = self.current_path_action
178
179                    self.current['entries'].append(entry)
180
181            def characters(self, data):
182                self.current_field.append(data)
183
184       
185        handler = SvnXMLLogHandler()
186        parseString(log.getvalue(), handler)
187        return handler.changesets
188   
189    def _applyChangeset(self, root, changeset):
190        svnup = SvnUpdate(working_dir=root)
191        out = svnup(output=True, entry='.', revision=changeset.revision)       
192        result = []
193        for line in out:
194            if len(line)>2 and line[0] == 'C' and line[1] == ' ':
195                result.append(line[2:-1])
196           
197        return result
198       
199    ## SyncronizableTargetWorkingDir
200
201    def _addEntry(self, root, entry):
202        """
203        Add a new entry, maybe registering the directory as well.
204        """
205
206        from os.path import split, join, exists
207
208        basedir = split(entry)[0]
209        if basedir and not exists(join(basedir, '.svn')):
210            self._addEntry(root, basedir)
211
212        c = SvnAdd(working_dir=root)
213        c(entry=entry)
214
215    def _checkoutUpstreamRevision(self, basedir, repository, module, revision):
216        """
217        Concretely do the checkout of the upstream revision.
218        """
219       
220        svnco = SvnCheckout(working_dir=basedir)
221        svnco(output=True, repository=repository, wc=module, revision=revision)
222       
223    def _commit(self,root, date, author, remark, changelog=None, entries=None):
224        """
225        Commit the changeset.
226        """
227
228        c = SvnCommit(working_dir=root)
229       
230        logmessage = remark + '\n'
231        if changelog:
232            logmessage = logmessage + changelog + '\n'
233           
234        if entries:
235            entries = ' '.join(entries)
236        else:
237            entries = '.'
238           
239        c(logmessage=logmessage, entries=entries)
240       
241    def _removeEntry(self, root, entry):
242        """
243        Remove an entry.
244        """
245
246        c = SvnRemove(working_dir=root)
247        c(entry=entry)
248
249    def _renameEntry(self, root, oldentry, newentry):
250        """
251        Rename an entry.
252        """
253
254        c = SvnMv(working_dir=root)
255        c(old=oldentry, new=newentry)
256
257    def _initializeWorkingDir(self, root, addentry=None):
258        """
259        Add the given directory to an already existing svn working tree.
260        """
261       
262        SyncronizableTargetWorkingDir._initializeWorkingDir(self, root, SvnAdd)
Note: See TracBrowser for help on using the repository browser.