##// END OF EJS Templates
convert/mtn: add support for using monotone's "automate stdio" when available...
Daniel Atallah -
r13760:ed97955e default
parent child Browse files
Show More
@@ -19,6 +19,7 class monotone_source(converter_source,
19
19
20 self.ui = ui
20 self.ui = ui
21 self.path = path
21 self.path = path
22 self.automatestdio = False
22
23
23 norepo = NoRepo(_("%s does not look like a monotone repository")
24 norepo = NoRepo(_("%s does not look like a monotone repository")
24 % path)
25 % path)
@@ -73,9 +74,102 class monotone_source(converter_source,
73 self.rev = rev
74 self.rev = rev
74
75
75 def mtnrun(self, *args, **kwargs):
76 def mtnrun(self, *args, **kwargs):
77 if self.automatestdio:
78 return self.mtnrunstdio(*args, **kwargs)
79 else:
80 return self.mtnrunsingle(*args, **kwargs)
81
82 def mtnrunsingle(self, *args, **kwargs):
76 kwargs['d'] = self.path
83 kwargs['d'] = self.path
77 return self.run0('automate', *args, **kwargs)
84 return self.run0('automate', *args, **kwargs)
78
85
86 def mtnrunstdio(self, *args, **kwargs):
87 # Prepare the command in automate stdio format
88 command = []
89 for k, v in kwargs.iteritems():
90 command.append("%s:%s" % (len(k), k))
91 if v:
92 command.append("%s:%s" % (len(v), v))
93 if command:
94 command.insert(0, 'o')
95 command.append('e')
96
97 command.append('l')
98 for arg in args:
99 command += "%s:%s" % (len(arg), arg)
100 command.append('e')
101 command = ''.join(command)
102
103 self.ui.debug("mtn: sending '%s'\n" % command)
104 self.mtnwritefp.write(command)
105 self.mtnwritefp.flush()
106
107 return self.mtnstdioreadcommandoutput(command)
108
109 def mtnstdioreadpacket(self):
110 read = None
111 commandnbr = ''
112 while read != ':':
113 read = self.mtnreadfp.read(1)
114 if not read:
115 raise util.Abort(_('bad mtn packet - no end of commandnbr'))
116 commandnbr += read
117 commandnbr = commandnbr[:-1]
118
119 stream = self.mtnreadfp.read(1)
120 if stream not in 'mewptl':
121 raise util.Abort(_('bad mtn packet - bad stream type %s' % stream))
122
123 read = self.mtnreadfp.read(1)
124 if read != ':':
125 raise util.Abort(_('bad mtn packet - no divider before size'))
126
127 read = None
128 lengthstr = ''
129 while read != ':':
130 read = self.mtnreadfp.read(1)
131 if not read:
132 raise util.Abort(_('bad mtn packet - no end of packet size'))
133 lengthstr += read
134 try:
135 length = long(lengthstr[:-1])
136 except TypeError:
137 raise util.Abort(_('bad mtn packet - bad packet size %s')
138 % lengthstr)
139
140 read = self.mtnreadfp.read(length)
141 if len(read) != length:
142 raise util.Abort(_("bad mtn packet - unable to read full packet "
143 "read %s of %s") % (len(read), length))
144
145 return (commandnbr, stream, length, read)
146
147 def mtnstdioreadcommandoutput(self, command):
148 retval = ''
149 while True:
150 commandnbr, stream, length, output = self.mtnstdioreadpacket()
151 self.ui.debug('mtn: read packet %s:%s:%s\n' %
152 (commandnbr, stream, length))
153
154 if stream == 'l':
155 # End of command
156 if output != '0':
157 raise util.Abort(_("mtn command '%s' returned %s") %
158 (command, output))
159 break
160 elif stream in 'ew':
161 # Error, warning output
162 self.ui.warn(_('%s error:\n') % self.command)
163 self.ui.warn(output)
164 elif stream == 'p':
165 # Progress messages
166 self.ui.debug('mtn: ' + output)
167 elif stream == 'm':
168 # Main stream - command output
169 retval = output
170
171 return retval
172
79 def mtnloadmanifest(self, rev):
173 def mtnloadmanifest(self, rev):
80 if self.manifest_rev == rev:
174 if self.manifest_rev == rev:
81 return
175 return
@@ -225,3 +319,43 class monotone_source(converter_source,
225 # This function is only needed to support --filemap
319 # This function is only needed to support --filemap
226 # ... and we don't support that
320 # ... and we don't support that
227 raise NotImplementedError()
321 raise NotImplementedError()
322
323 def before(self):
324 # Check if we have a new enough version to use automate stdio
325 version = 0.0
326 try:
327 versionstr = self.mtnrunsingle("interface_version")
328 version = float(versionstr)
329 except Exception:
330 raise util.Abort(_("unable to determine mtn automate interface "
331 "version"))
332
333 if version >= 12.0:
334 self.automatestdio = True
335 self.ui.debug("mtn automate version %s - using automate stdio\n" %
336 version)
337
338 # launch the long-running automate stdio process
339 self.mtnwritefp, self.mtnreadfp = self._run2('automate', 'stdio',
340 '-d', self.path)
341 # read the headers
342 read = self.mtnreadfp.readline()
343 if read != 'format-version: 2\n':
344 raise util.Abort(_('mtn automate stdio header unexpected: %s')
345 % read)
346 while read != '\n':
347 read = self.mtnreadfp.readline()
348 if not read:
349 raise util.Abort(_("failed to reach end of mtn automate "
350 "stdio headers"))
351 else:
352 self.ui.debug("mtn automate version %s - not using automate stdio "
353 "(automate >= 12.0 - mtn >= 0.46 is needed)\n" % version)
354
355 def after(self):
356 if self.automatestdio:
357 self.mtnwritefp.close()
358 self.mtnwritefp = None
359 self.mtnreadfp.close()
360 self.mtnreadfp = None
361
General Comments 0
You need to be logged in to leave comments. Login now