/stdhome

To get this branch, use:
bzr branch http://bzr.ed.am/stdhome

« back to all changes in this revision

Viewing changes to lib/stdhome/vcs/bzr.py

  • Committer: Tim Marston
  • Date: 2014-03-19 20:03:32 UTC
  • Revision ID: tim@ed.am-20140319200332-6jpt67qon2ugmg2n
changed wording of status command output

Show diffs side-by-side

added added

removed removed

21
21
 
22
22
import subprocess, os, re, shutil
23
23
from subprocess import Popen
24
 
import stdhome.the as the
25
24
import StringIO
26
 
 
27
 
 
28
 
class VcsBzr:
 
25
from vcs import Vcs
 
26
from stdhome import the
 
27
 
 
28
 
 
29
class BzrVcs( Vcs ):
29
30
 
30
31
 
31
32
        def __init__( self, dir ):
44
45
                os.mkdir( self.dir )
45
46
 
46
47
                # bzr init
47
 
                p = Popen( [ 'bzr', 'init', '.' ], cwd = self.dir,
48
 
                                   stdout = subprocess.PIPE, stderr = subprocess.STDOUT )
49
 
                output = p.communicate()[ 0 ]
50
 
                if p.returncode > 0:
 
48
                try:
 
49
                        self.run( [ 'bzr', 'init', '.' ] )
 
50
                except self.VcsError as e:
51
51
 
52
52
                        # attempt to clean-up dir
53
53
                        try:
55
55
                        except OSError:
56
56
                                pass
57
57
 
58
 
                        raise the.program.FatalError( 'bzr init failed', output )
 
58
                        raise
59
59
 
60
60
 
61
61
        def checkout( self, url ):
68
68
                os.mkdir( self.dir )
69
69
 
70
70
                # bzr co
71
 
                p = Popen( [ 'bzr', 'co', url, '.' ], cwd = self.dir,
72
 
                                   stdout = subprocess.PIPE, stderr = subprocess.STDOUT )
73
 
                output = p.communicate()[ 0 ]
74
 
                if p.returncode > 0:
 
71
                try:
 
72
                        self.run( [ 'bzr', 'checkout', url, '.' ] )
 
73
                except self.VcsError as e:
75
74
 
76
75
                        # attempt to clean-up dir
77
76
                        try:
79
78
                        except OSError:
80
79
                                pass
81
80
 
82
 
                        raise the.program.FatalError( 'bzr checkout failed', output )
83
 
 
84
 
 
85
 
        def revert( self ):
 
81
                        raise
 
82
 
 
83
 
 
84
        def get_revno( self ):
 
85
                """Obtain some sort of revision identifier
 
86
                """
 
87
 
 
88
                # bzr revert
 
89
                output = self.run( [ 'bzr', 'revno', '--tree' ] )
 
90
 
 
91
                # parse revno
 
92
                buf = StringIO.StringIO( output )
 
93
                return buf.readline().rstrip()
 
94
 
 
95
 
 
96
        def revert( self, revno = None ):
86
97
                """Revert the branch so that there are no outstanding changes or unknown files.
 
98
                If a revno is supplied, then the repository is reverted to that
 
99
                revision.
87
100
                """
88
101
 
89
102
                # bzr revert
90
 
                p = Popen( [ 'bzr', 'revert', '--no-backup' ], cwd = self.dir,
91
 
                                   stdout = subprocess.PIPE, stderr = subprocess.STDOUT )
92
 
                output = p.communicate()[ 0 ]
93
 
                if p.returncode > 0:
94
 
                        raise the.program.FatalError( 'bzr revert failed', output )
 
103
                self.run( [ 'bzr', 'revert', '--no-backup' ] )
95
104
 
96
105
                # bzr st
97
 
                p = Popen( [ 'bzr', 'st' ], cwd = self.dir,
98
 
                                   stdout = subprocess.PIPE, stderr = subprocess.STDOUT )
99
 
                output = p.communicate()[ 0 ]
100
 
                if p.returncode > 0:
101
 
                        raise the.program.FatalError( 'bzr status failed', output )
 
106
                output = self.run( [ 'bzr', 'status' ] )
102
107
                files = self.parse_file_blocks( output )
103
108
 
104
109
                # remove unknown files
112
117
                                else:
113
118
                                        raise RuntimeError( 'exotic file in repo: %s' % file )
114
119
 
 
120
                # if a revision identifyer has been given, update to that
 
121
                if revno is not None:
 
122
 
 
123
                        # bzr update
 
124
                        self.run( [ 'bzr', 'update', '-r', revno ] )
 
125
 
115
126
 
116
127
        def update( self ):
117
 
                """Update the branch, pulling down any upstream changes and merging them.
 
128
                """Update the branch, pulling down any upstream changes and merging them.  This
 
129
                method returns a list of the files that were modified as part of this
 
130
                operation.
118
131
                """
119
132
 
120
 
                # bzr update
121
 
                p = Popen( [ 'bzr', 'update' ], cwd = self.dir,
122
 
                                   stdout = subprocess.PIPE, stderr = subprocess.STDOUT )
123
 
                output = p.communicate()[ 0 ]
124
 
                if p.returncode > 0:
125
 
                        raise the.program.FatalError( 'bzr update failed', output )
 
133
#               WARNING: the following might cause bzr to ask for your ssh password more than
 
134
#               once during an update!!!
 
135
#
 
136
#               # get revno
 
137
#               revno = self.get_revno()
 
138
#
 
139
#               # update to current revision (pull in history without updating tree)
 
140
#               self.run( [ 'bzr', 'update', '-r', revno ] )
 
141
#
 
142
#               # get log output
 
143
#               next_revno = str( int( revno ) + 1 )
 
144
#               output = self.run( [ 'bzr', 'log', '-r', next_revno + '..' ] )
 
145
#
 
146
#               # parse output
 
147
#               keep_files = list()
 
148
#               buf = StringIO.StringIO( output )
 
149
#               in_message = False
 
150
#               for line in buf:
 
151
#                       line = line.rstrip( '\n' )
 
152
#                       if line.lower() == 'message:':
 
153
#                               in_message = True
 
154
#                       elif in_message:
 
155
#                               if line[ : 2 ] != '  ':
 
156
#                                       in_message = False
 
157
#                               else:
 
158
#                                       line = line[ 2 : ]
 
159
#
 
160
#                                       # process directives
 
161
#                                       if line[ : 6 ].lower() == 'keep: ':
 
162
#                                               file = line[ 6 : ]
 
163
#                                               if file in rename_files: file = rename_files[ file ]
 
164
#                                               keep_files.append( file )
 
165
#                                       elif line[ : 8 ].lower() == 'rename: ':
 
166
#                                               rename_from = line[ 8 : ]
 
167
#                                       elif line[ : 4 ].lower() == 'to: ':
 
168
#                                               if rename_from in rename_files:
 
169
#                                                       rename_from = rename_files[ rename_from ]
 
170
#                                               rename_files[ line[ 4 : ] ] = rename_from
 
171
 
 
172
                # bzr update properly
 
173
                output = self.run( [ 'bzr', 'update' ] )
 
174
 
 
175
                # parse output (see logic in report() in bzrlib/delta.py)
 
176
                files = list()
 
177
                buf = StringIO.StringIO( output )
 
178
                for line in buf:
 
179
                        if not re.search( '^[-R+ ?][K NMD!][* ] ', line ): continue
 
180
                        line = line.rstrip()
 
181
                        if the.verbose > 1: print '  %s' % line
 
182
 
 
183
                        # renames show before and after file names
 
184
                        matches = re.search( '^R.. (.*?)[/@+]? => (.*?)[/@+]?$', line )
 
185
                        if matches:
 
186
                                files.append( matches.group( 1 ) )
 
187
                                files.append( matches.group( 2 ) )
 
188
                                continue
 
189
 
 
190
                        # kind changes shows the same name twice
 
191
                        matches = re.search( '^.K. (.*?)[/@+]? => (.*?)[/@+]?$', line )
 
192
                        if matches:
 
193
                                files.append( matches.group( 1 ) )
 
194
                                continue
 
195
 
 
196
                        # other entries have only one filename
 
197
                        matches = re.search( '^... (.*?)[/@+]?$', line )
 
198
                        if matches:
 
199
                                files.append( matches.group( 1 ) )
 
200
                                continue
 
201
 
 
202
                        raise RuntimeError(
 
203
                                'failed to parse bzr update output line:\n%' % line )
 
204
 
 
205
                return files
126
206
 
127
207
 
128
208
        def has_changes( self ):
130
210
                """
131
211
 
132
212
                # bzr status
133
 
                p = Popen( [ 'bzr', 'status', '--no-pending' ], cwd = self.dir,
134
 
                                   stdout = subprocess.PIPE, stderr = subprocess.STDOUT )
135
 
                output = p.communicate()[ 0 ]
136
 
                if p.returncode > 0:
137
 
                        raise the.program.FatalError( 'bzr status failed', output )
 
213
                output = self.run( [ 'bzr', 'status', '--no-pending' ] )
 
214
 
 
215
                # parse output
138
216
                files = self.parse_file_blocks( output )
139
217
                return True if len( files ) else False
140
218
 
144
222
                """
145
223
 
146
224
                # bzr status
147
 
                p = Popen( [ 'bzr', 'status', '--no-pending' ], cwd = self.dir,
148
 
                                   stdout = subprocess.PIPE, stderr = subprocess.STDOUT )
149
 
                output = p.communicate()[ 0 ]
150
 
                if p.returncode > 0:
151
 
                        raise the.program.FatalError( 'bzr status failed', output )
 
225
                output = self.run( [ 'bzr', 'status', '--no-pending' ] )
 
226
 
 
227
                # parse output
152
228
                files = self.parse_file_blocks( output )
153
229
                return files['conflicts'] if 'conflicts' in files else None
154
230
 
155
231
 
 
232
        def run( self, cmd ):
 
233
                if the.verbose > 1: print 'exec: %s' % ' '.join( cmd )
 
234
                p = Popen( cmd, cwd = self.dir,
 
235
                                   stdout = subprocess.PIPE, stderr = subprocess.STDOUT )
 
236
                output = p.communicate()[ 0 ]
 
237
                if p.returncode > 0:
 
238
                        raise self.VcsError( ' '.join( cmd[ : 2 ] ), output )
 
239
                return output
 
240
 
 
241
 
156
242
        def parse_file_blocks( self, output ):
157
243
                res = dict()
158
244
                current = None