##// END OF EJS Templates
convert: use bytes for value in extra dict...
Manuel Jacob -
r45652:e699cebc stable
parent child Browse files
Show More
@@ -1,411 +1,411
1 # monotone.py - monotone support for the convert extension
1 # monotone.py - monotone support for the convert extension
2 #
2 #
3 # Copyright 2008, 2009 Mikkel Fahnoe Jorgensen <mikkel@dvide.com> and
3 # Copyright 2008, 2009 Mikkel Fahnoe Jorgensen <mikkel@dvide.com> and
4 # others
4 # others
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import os
10 import os
11 import re
11 import re
12
12
13 from mercurial.i18n import _
13 from mercurial.i18n import _
14 from mercurial.pycompat import open
14 from mercurial.pycompat import open
15 from mercurial import (
15 from mercurial import (
16 error,
16 error,
17 pycompat,
17 pycompat,
18 )
18 )
19 from mercurial.utils import dateutil
19 from mercurial.utils import dateutil
20
20
21 from . import common
21 from . import common
22
22
23
23
24 class monotone_source(common.converter_source, common.commandline):
24 class monotone_source(common.converter_source, common.commandline):
25 def __init__(self, ui, repotype, path=None, revs=None):
25 def __init__(self, ui, repotype, path=None, revs=None):
26 common.converter_source.__init__(self, ui, repotype, path, revs)
26 common.converter_source.__init__(self, ui, repotype, path, revs)
27 if revs and len(revs) > 1:
27 if revs and len(revs) > 1:
28 raise error.Abort(
28 raise error.Abort(
29 _(
29 _(
30 b'monotone source does not support specifying '
30 b'monotone source does not support specifying '
31 b'multiple revs'
31 b'multiple revs'
32 )
32 )
33 )
33 )
34 common.commandline.__init__(self, ui, b'mtn')
34 common.commandline.__init__(self, ui, b'mtn')
35
35
36 self.ui = ui
36 self.ui = ui
37 self.path = path
37 self.path = path
38 self.automatestdio = False
38 self.automatestdio = False
39 self.revs = revs
39 self.revs = revs
40
40
41 norepo = common.NoRepo(
41 norepo = common.NoRepo(
42 _(b"%s does not look like a monotone repository") % path
42 _(b"%s does not look like a monotone repository") % path
43 )
43 )
44 if not os.path.exists(os.path.join(path, b'_MTN')):
44 if not os.path.exists(os.path.join(path, b'_MTN')):
45 # Could be a monotone repository (SQLite db file)
45 # Could be a monotone repository (SQLite db file)
46 try:
46 try:
47 f = open(path, b'rb')
47 f = open(path, b'rb')
48 header = f.read(16)
48 header = f.read(16)
49 f.close()
49 f.close()
50 except IOError:
50 except IOError:
51 header = b''
51 header = b''
52 if header != b'SQLite format 3\x00':
52 if header != b'SQLite format 3\x00':
53 raise norepo
53 raise norepo
54
54
55 # regular expressions for parsing monotone output
55 # regular expressions for parsing monotone output
56 space = br'\s*'
56 space = br'\s*'
57 name = br'\s+"((?:\\"|[^"])*)"\s*'
57 name = br'\s+"((?:\\"|[^"])*)"\s*'
58 value = name
58 value = name
59 revision = br'\s+\[(\w+)\]\s*'
59 revision = br'\s+\[(\w+)\]\s*'
60 lines = br'(?:.|\n)+'
60 lines = br'(?:.|\n)+'
61
61
62 self.dir_re = re.compile(space + b"dir" + name)
62 self.dir_re = re.compile(space + b"dir" + name)
63 self.file_re = re.compile(
63 self.file_re = re.compile(
64 space + b"file" + name + b"content" + revision
64 space + b"file" + name + b"content" + revision
65 )
65 )
66 self.add_file_re = re.compile(
66 self.add_file_re = re.compile(
67 space + b"add_file" + name + b"content" + revision
67 space + b"add_file" + name + b"content" + revision
68 )
68 )
69 self.patch_re = re.compile(
69 self.patch_re = re.compile(
70 space + b"patch" + name + b"from" + revision + b"to" + revision
70 space + b"patch" + name + b"from" + revision + b"to" + revision
71 )
71 )
72 self.rename_re = re.compile(space + b"rename" + name + b"to" + name)
72 self.rename_re = re.compile(space + b"rename" + name + b"to" + name)
73 self.delete_re = re.compile(space + b"delete" + name)
73 self.delete_re = re.compile(space + b"delete" + name)
74 self.tag_re = re.compile(space + b"tag" + name + b"revision" + revision)
74 self.tag_re = re.compile(space + b"tag" + name + b"revision" + revision)
75 self.cert_re = re.compile(
75 self.cert_re = re.compile(
76 lines + space + b"name" + name + b"value" + value
76 lines + space + b"name" + name + b"value" + value
77 )
77 )
78
78
79 attr = space + b"file" + lines + space + b"attr" + space
79 attr = space + b"file" + lines + space + b"attr" + space
80 self.attr_execute_re = re.compile(
80 self.attr_execute_re = re.compile(
81 attr + b'"mtn:execute"' + space + b'"true"'
81 attr + b'"mtn:execute"' + space + b'"true"'
82 )
82 )
83
83
84 # cached data
84 # cached data
85 self.manifest_rev = None
85 self.manifest_rev = None
86 self.manifest = None
86 self.manifest = None
87 self.files = None
87 self.files = None
88 self.dirs = None
88 self.dirs = None
89
89
90 common.checktool(b'mtn', abort=False)
90 common.checktool(b'mtn', abort=False)
91
91
92 def mtnrun(self, *args, **kwargs):
92 def mtnrun(self, *args, **kwargs):
93 if self.automatestdio:
93 if self.automatestdio:
94 return self.mtnrunstdio(*args, **kwargs)
94 return self.mtnrunstdio(*args, **kwargs)
95 else:
95 else:
96 return self.mtnrunsingle(*args, **kwargs)
96 return self.mtnrunsingle(*args, **kwargs)
97
97
98 def mtnrunsingle(self, *args, **kwargs):
98 def mtnrunsingle(self, *args, **kwargs):
99 kwargs['d'] = self.path
99 kwargs['d'] = self.path
100 return self.run0(b'automate', *args, **kwargs)
100 return self.run0(b'automate', *args, **kwargs)
101
101
102 def mtnrunstdio(self, *args, **kwargs):
102 def mtnrunstdio(self, *args, **kwargs):
103 # Prepare the command in automate stdio format
103 # Prepare the command in automate stdio format
104 kwargs = pycompat.byteskwargs(kwargs)
104 kwargs = pycompat.byteskwargs(kwargs)
105 command = []
105 command = []
106 for k, v in pycompat.iteritems(kwargs):
106 for k, v in pycompat.iteritems(kwargs):
107 command.append(b"%d:%s" % (len(k), k))
107 command.append(b"%d:%s" % (len(k), k))
108 if v:
108 if v:
109 command.append(b"%d:%s" % (len(v), v))
109 command.append(b"%d:%s" % (len(v), v))
110 if command:
110 if command:
111 command.insert(0, b'o')
111 command.insert(0, b'o')
112 command.append(b'e')
112 command.append(b'e')
113
113
114 command.append(b'l')
114 command.append(b'l')
115 for arg in args:
115 for arg in args:
116 command.append(b"%d:%s" % (len(arg), arg))
116 command.append(b"%d:%s" % (len(arg), arg))
117 command.append(b'e')
117 command.append(b'e')
118 command = b''.join(command)
118 command = b''.join(command)
119
119
120 self.ui.debug(b"mtn: sending '%s'\n" % command)
120 self.ui.debug(b"mtn: sending '%s'\n" % command)
121 self.mtnwritefp.write(command)
121 self.mtnwritefp.write(command)
122 self.mtnwritefp.flush()
122 self.mtnwritefp.flush()
123
123
124 return self.mtnstdioreadcommandoutput(command)
124 return self.mtnstdioreadcommandoutput(command)
125
125
126 def mtnstdioreadpacket(self):
126 def mtnstdioreadpacket(self):
127 read = None
127 read = None
128 commandnbr = b''
128 commandnbr = b''
129 while read != b':':
129 while read != b':':
130 read = self.mtnreadfp.read(1)
130 read = self.mtnreadfp.read(1)
131 if not read:
131 if not read:
132 raise error.Abort(_(b'bad mtn packet - no end of commandnbr'))
132 raise error.Abort(_(b'bad mtn packet - no end of commandnbr'))
133 commandnbr += read
133 commandnbr += read
134 commandnbr = commandnbr[:-1]
134 commandnbr = commandnbr[:-1]
135
135
136 stream = self.mtnreadfp.read(1)
136 stream = self.mtnreadfp.read(1)
137 if stream not in b'mewptl':
137 if stream not in b'mewptl':
138 raise error.Abort(
138 raise error.Abort(
139 _(b'bad mtn packet - bad stream type %s') % stream
139 _(b'bad mtn packet - bad stream type %s') % stream
140 )
140 )
141
141
142 read = self.mtnreadfp.read(1)
142 read = self.mtnreadfp.read(1)
143 if read != b':':
143 if read != b':':
144 raise error.Abort(_(b'bad mtn packet - no divider before size'))
144 raise error.Abort(_(b'bad mtn packet - no divider before size'))
145
145
146 read = None
146 read = None
147 lengthstr = b''
147 lengthstr = b''
148 while read != b':':
148 while read != b':':
149 read = self.mtnreadfp.read(1)
149 read = self.mtnreadfp.read(1)
150 if not read:
150 if not read:
151 raise error.Abort(_(b'bad mtn packet - no end of packet size'))
151 raise error.Abort(_(b'bad mtn packet - no end of packet size'))
152 lengthstr += read
152 lengthstr += read
153 try:
153 try:
154 length = pycompat.long(lengthstr[:-1])
154 length = pycompat.long(lengthstr[:-1])
155 except TypeError:
155 except TypeError:
156 raise error.Abort(
156 raise error.Abort(
157 _(b'bad mtn packet - bad packet size %s') % lengthstr
157 _(b'bad mtn packet - bad packet size %s') % lengthstr
158 )
158 )
159
159
160 read = self.mtnreadfp.read(length)
160 read = self.mtnreadfp.read(length)
161 if len(read) != length:
161 if len(read) != length:
162 raise error.Abort(
162 raise error.Abort(
163 _(
163 _(
164 b"bad mtn packet - unable to read full packet "
164 b"bad mtn packet - unable to read full packet "
165 b"read %s of %s"
165 b"read %s of %s"
166 )
166 )
167 % (len(read), length)
167 % (len(read), length)
168 )
168 )
169
169
170 return (commandnbr, stream, length, read)
170 return (commandnbr, stream, length, read)
171
171
172 def mtnstdioreadcommandoutput(self, command):
172 def mtnstdioreadcommandoutput(self, command):
173 retval = []
173 retval = []
174 while True:
174 while True:
175 commandnbr, stream, length, output = self.mtnstdioreadpacket()
175 commandnbr, stream, length, output = self.mtnstdioreadpacket()
176 self.ui.debug(
176 self.ui.debug(
177 b'mtn: read packet %s:%s:%d\n' % (commandnbr, stream, length)
177 b'mtn: read packet %s:%s:%d\n' % (commandnbr, stream, length)
178 )
178 )
179
179
180 if stream == b'l':
180 if stream == b'l':
181 # End of command
181 # End of command
182 if output != b'0':
182 if output != b'0':
183 raise error.Abort(
183 raise error.Abort(
184 _(b"mtn command '%s' returned %s") % (command, output)
184 _(b"mtn command '%s' returned %s") % (command, output)
185 )
185 )
186 break
186 break
187 elif stream in b'ew':
187 elif stream in b'ew':
188 # Error, warning output
188 # Error, warning output
189 self.ui.warn(_(b'%s error:\n') % self.command)
189 self.ui.warn(_(b'%s error:\n') % self.command)
190 self.ui.warn(output)
190 self.ui.warn(output)
191 elif stream == b'p':
191 elif stream == b'p':
192 # Progress messages
192 # Progress messages
193 self.ui.debug(b'mtn: ' + output)
193 self.ui.debug(b'mtn: ' + output)
194 elif stream == b'm':
194 elif stream == b'm':
195 # Main stream - command output
195 # Main stream - command output
196 retval.append(output)
196 retval.append(output)
197
197
198 return b''.join(retval)
198 return b''.join(retval)
199
199
200 def mtnloadmanifest(self, rev):
200 def mtnloadmanifest(self, rev):
201 if self.manifest_rev == rev:
201 if self.manifest_rev == rev:
202 return
202 return
203 self.manifest = self.mtnrun(b"get_manifest_of", rev).split(b"\n\n")
203 self.manifest = self.mtnrun(b"get_manifest_of", rev).split(b"\n\n")
204 self.manifest_rev = rev
204 self.manifest_rev = rev
205 self.files = {}
205 self.files = {}
206 self.dirs = {}
206 self.dirs = {}
207
207
208 for e in self.manifest:
208 for e in self.manifest:
209 m = self.file_re.match(e)
209 m = self.file_re.match(e)
210 if m:
210 if m:
211 attr = b""
211 attr = b""
212 name = m.group(1)
212 name = m.group(1)
213 node = m.group(2)
213 node = m.group(2)
214 if self.attr_execute_re.match(e):
214 if self.attr_execute_re.match(e):
215 attr += b"x"
215 attr += b"x"
216 self.files[name] = (node, attr)
216 self.files[name] = (node, attr)
217 m = self.dir_re.match(e)
217 m = self.dir_re.match(e)
218 if m:
218 if m:
219 self.dirs[m.group(1)] = True
219 self.dirs[m.group(1)] = True
220
220
221 def mtnisfile(self, name, rev):
221 def mtnisfile(self, name, rev):
222 # a non-file could be a directory or a deleted or renamed file
222 # a non-file could be a directory or a deleted or renamed file
223 self.mtnloadmanifest(rev)
223 self.mtnloadmanifest(rev)
224 return name in self.files
224 return name in self.files
225
225
226 def mtnisdir(self, name, rev):
226 def mtnisdir(self, name, rev):
227 self.mtnloadmanifest(rev)
227 self.mtnloadmanifest(rev)
228 return name in self.dirs
228 return name in self.dirs
229
229
230 def mtngetcerts(self, rev):
230 def mtngetcerts(self, rev):
231 certs = {
231 certs = {
232 b"author": b"<missing>",
232 b"author": b"<missing>",
233 b"date": b"<missing>",
233 b"date": b"<missing>",
234 b"changelog": b"<missing>",
234 b"changelog": b"<missing>",
235 b"branch": b"<missing>",
235 b"branch": b"<missing>",
236 }
236 }
237 certlist = self.mtnrun(b"certs", rev)
237 certlist = self.mtnrun(b"certs", rev)
238 # mtn < 0.45:
238 # mtn < 0.45:
239 # key "test@selenic.com"
239 # key "test@selenic.com"
240 # mtn >= 0.45:
240 # mtn >= 0.45:
241 # key [ff58a7ffb771907c4ff68995eada1c4da068d328]
241 # key [ff58a7ffb771907c4ff68995eada1c4da068d328]
242 certlist = re.split(br'\n\n {6}key ["\[]', certlist)
242 certlist = re.split(br'\n\n {6}key ["\[]', certlist)
243 for e in certlist:
243 for e in certlist:
244 m = self.cert_re.match(e)
244 m = self.cert_re.match(e)
245 if m:
245 if m:
246 name, value = m.groups()
246 name, value = m.groups()
247 value = value.replace(br'\"', b'"')
247 value = value.replace(br'\"', b'"')
248 value = value.replace(br'\\', b'\\')
248 value = value.replace(br'\\', b'\\')
249 certs[name] = value
249 certs[name] = value
250 # Monotone may have subsecond dates: 2005-02-05T09:39:12.364306
250 # Monotone may have subsecond dates: 2005-02-05T09:39:12.364306
251 # and all times are stored in UTC
251 # and all times are stored in UTC
252 certs[b"date"] = certs[b"date"].split(b'.')[0] + b" UTC"
252 certs[b"date"] = certs[b"date"].split(b'.')[0] + b" UTC"
253 return certs
253 return certs
254
254
255 # implement the converter_source interface:
255 # implement the converter_source interface:
256
256
257 def getheads(self):
257 def getheads(self):
258 if not self.revs:
258 if not self.revs:
259 return self.mtnrun(b"leaves").splitlines()
259 return self.mtnrun(b"leaves").splitlines()
260 else:
260 else:
261 return self.revs
261 return self.revs
262
262
263 def getchanges(self, rev, full):
263 def getchanges(self, rev, full):
264 if full:
264 if full:
265 raise error.Abort(
265 raise error.Abort(
266 _(b"convert from monotone does not support --full")
266 _(b"convert from monotone does not support --full")
267 )
267 )
268 revision = self.mtnrun(b"get_revision", rev).split(b"\n\n")
268 revision = self.mtnrun(b"get_revision", rev).split(b"\n\n")
269 files = {}
269 files = {}
270 ignoremove = {}
270 ignoremove = {}
271 renameddirs = []
271 renameddirs = []
272 copies = {}
272 copies = {}
273 for e in revision:
273 for e in revision:
274 m = self.add_file_re.match(e)
274 m = self.add_file_re.match(e)
275 if m:
275 if m:
276 files[m.group(1)] = rev
276 files[m.group(1)] = rev
277 ignoremove[m.group(1)] = rev
277 ignoremove[m.group(1)] = rev
278 m = self.patch_re.match(e)
278 m = self.patch_re.match(e)
279 if m:
279 if m:
280 files[m.group(1)] = rev
280 files[m.group(1)] = rev
281 # Delete/rename is handled later when the convert engine
281 # Delete/rename is handled later when the convert engine
282 # discovers an IOError exception from getfile,
282 # discovers an IOError exception from getfile,
283 # but only if we add the "from" file to the list of changes.
283 # but only if we add the "from" file to the list of changes.
284 m = self.delete_re.match(e)
284 m = self.delete_re.match(e)
285 if m:
285 if m:
286 files[m.group(1)] = rev
286 files[m.group(1)] = rev
287 m = self.rename_re.match(e)
287 m = self.rename_re.match(e)
288 if m:
288 if m:
289 toname = m.group(2)
289 toname = m.group(2)
290 fromname = m.group(1)
290 fromname = m.group(1)
291 if self.mtnisfile(toname, rev):
291 if self.mtnisfile(toname, rev):
292 ignoremove[toname] = 1
292 ignoremove[toname] = 1
293 copies[toname] = fromname
293 copies[toname] = fromname
294 files[toname] = rev
294 files[toname] = rev
295 files[fromname] = rev
295 files[fromname] = rev
296 elif self.mtnisdir(toname, rev):
296 elif self.mtnisdir(toname, rev):
297 renameddirs.append((fromname, toname))
297 renameddirs.append((fromname, toname))
298
298
299 # Directory renames can be handled only once we have recorded
299 # Directory renames can be handled only once we have recorded
300 # all new files
300 # all new files
301 for fromdir, todir in renameddirs:
301 for fromdir, todir in renameddirs:
302 renamed = {}
302 renamed = {}
303 for tofile in self.files:
303 for tofile in self.files:
304 if tofile in ignoremove:
304 if tofile in ignoremove:
305 continue
305 continue
306 if tofile.startswith(todir + b'/'):
306 if tofile.startswith(todir + b'/'):
307 renamed[tofile] = fromdir + tofile[len(todir) :]
307 renamed[tofile] = fromdir + tofile[len(todir) :]
308 # Avoid chained moves like:
308 # Avoid chained moves like:
309 # d1(/a) => d3/d1(/a)
309 # d1(/a) => d3/d1(/a)
310 # d2 => d3
310 # d2 => d3
311 ignoremove[tofile] = 1
311 ignoremove[tofile] = 1
312 for tofile, fromfile in renamed.items():
312 for tofile, fromfile in renamed.items():
313 self.ui.debug(
313 self.ui.debug(
314 b"copying file in renamed directory from '%s' to '%s'"
314 b"copying file in renamed directory from '%s' to '%s'"
315 % (fromfile, tofile),
315 % (fromfile, tofile),
316 b'\n',
316 b'\n',
317 )
317 )
318 files[tofile] = rev
318 files[tofile] = rev
319 copies[tofile] = fromfile
319 copies[tofile] = fromfile
320 for fromfile in renamed.values():
320 for fromfile in renamed.values():
321 files[fromfile] = rev
321 files[fromfile] = rev
322
322
323 return (files.items(), copies, set())
323 return (files.items(), copies, set())
324
324
325 def getfile(self, name, rev):
325 def getfile(self, name, rev):
326 if not self.mtnisfile(name, rev):
326 if not self.mtnisfile(name, rev):
327 return None, None
327 return None, None
328 try:
328 try:
329 data = self.mtnrun(b"get_file_of", name, r=rev)
329 data = self.mtnrun(b"get_file_of", name, r=rev)
330 except Exception:
330 except Exception:
331 return None, None
331 return None, None
332 self.mtnloadmanifest(rev)
332 self.mtnloadmanifest(rev)
333 node, attr = self.files.get(name, (None, b""))
333 node, attr = self.files.get(name, (None, b""))
334 return data, attr
334 return data, attr
335
335
336 def getcommit(self, rev):
336 def getcommit(self, rev):
337 extra = {}
337 extra = {}
338 certs = self.mtngetcerts(rev)
338 certs = self.mtngetcerts(rev)
339 if certs.get(b'suspend') == certs[b"branch"]:
339 if certs.get(b'suspend') == certs[b"branch"]:
340 extra[b'close'] = 1
340 extra[b'close'] = b'1'
341 dateformat = b"%Y-%m-%dT%H:%M:%S"
341 dateformat = b"%Y-%m-%dT%H:%M:%S"
342 return common.commit(
342 return common.commit(
343 author=certs[b"author"],
343 author=certs[b"author"],
344 date=dateutil.datestr(dateutil.strdate(certs[b"date"], dateformat)),
344 date=dateutil.datestr(dateutil.strdate(certs[b"date"], dateformat)),
345 desc=certs[b"changelog"],
345 desc=certs[b"changelog"],
346 rev=rev,
346 rev=rev,
347 parents=self.mtnrun(b"parents", rev).splitlines(),
347 parents=self.mtnrun(b"parents", rev).splitlines(),
348 branch=certs[b"branch"],
348 branch=certs[b"branch"],
349 extra=extra,
349 extra=extra,
350 )
350 )
351
351
352 def gettags(self):
352 def gettags(self):
353 tags = {}
353 tags = {}
354 for e in self.mtnrun(b"tags").split(b"\n\n"):
354 for e in self.mtnrun(b"tags").split(b"\n\n"):
355 m = self.tag_re.match(e)
355 m = self.tag_re.match(e)
356 if m:
356 if m:
357 tags[m.group(1)] = m.group(2)
357 tags[m.group(1)] = m.group(2)
358 return tags
358 return tags
359
359
360 def getchangedfiles(self, rev, i):
360 def getchangedfiles(self, rev, i):
361 # This function is only needed to support --filemap
361 # This function is only needed to support --filemap
362 # ... and we don't support that
362 # ... and we don't support that
363 raise NotImplementedError
363 raise NotImplementedError
364
364
365 def before(self):
365 def before(self):
366 # Check if we have a new enough version to use automate stdio
366 # Check if we have a new enough version to use automate stdio
367 try:
367 try:
368 versionstr = self.mtnrunsingle(b"interface_version")
368 versionstr = self.mtnrunsingle(b"interface_version")
369 version = float(versionstr)
369 version = float(versionstr)
370 except Exception:
370 except Exception:
371 raise error.Abort(
371 raise error.Abort(
372 _(b"unable to determine mtn automate interface version")
372 _(b"unable to determine mtn automate interface version")
373 )
373 )
374
374
375 if version >= 12.0:
375 if version >= 12.0:
376 self.automatestdio = True
376 self.automatestdio = True
377 self.ui.debug(
377 self.ui.debug(
378 b"mtn automate version %f - using automate stdio\n" % version
378 b"mtn automate version %f - using automate stdio\n" % version
379 )
379 )
380
380
381 # launch the long-running automate stdio process
381 # launch the long-running automate stdio process
382 self.mtnwritefp, self.mtnreadfp = self._run2(
382 self.mtnwritefp, self.mtnreadfp = self._run2(
383 b'automate', b'stdio', b'-d', self.path
383 b'automate', b'stdio', b'-d', self.path
384 )
384 )
385 # read the headers
385 # read the headers
386 read = self.mtnreadfp.readline()
386 read = self.mtnreadfp.readline()
387 if read != b'format-version: 2\n':
387 if read != b'format-version: 2\n':
388 raise error.Abort(
388 raise error.Abort(
389 _(b'mtn automate stdio header unexpected: %s') % read
389 _(b'mtn automate stdio header unexpected: %s') % read
390 )
390 )
391 while read != b'\n':
391 while read != b'\n':
392 read = self.mtnreadfp.readline()
392 read = self.mtnreadfp.readline()
393 if not read:
393 if not read:
394 raise error.Abort(
394 raise error.Abort(
395 _(
395 _(
396 b"failed to reach end of mtn automate "
396 b"failed to reach end of mtn automate "
397 b"stdio headers"
397 b"stdio headers"
398 )
398 )
399 )
399 )
400 else:
400 else:
401 self.ui.debug(
401 self.ui.debug(
402 b"mtn automate version %s - not using automate stdio "
402 b"mtn automate version %s - not using automate stdio "
403 b"(automate >= 12.0 - mtn >= 0.46 is needed)\n" % version
403 b"(automate >= 12.0 - mtn >= 0.46 is needed)\n" % version
404 )
404 )
405
405
406 def after(self):
406 def after(self):
407 if self.automatestdio:
407 if self.automatestdio:
408 self.mtnwritefp.close()
408 self.mtnwritefp.close()
409 self.mtnwritefp = None
409 self.mtnwritefp = None
410 self.mtnreadfp.close()
410 self.mtnreadfp.close()
411 self.mtnreadfp = None
411 self.mtnreadfp = None
General Comments 0
You need to be logged in to leave comments. Login now