##// END OF EJS Templates
py3: make sure regexes are bytes...
Pulkit Goyal -
r36411:54f4328a default
parent child Browse files
Show More
@@ -1,297 +1,297 b''
1 1 # cvs.py: CVS conversion code inspired by hg-cvs-import and git-cvsimport
2 2 #
3 3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7 from __future__ import absolute_import
8 8
9 9 import errno
10 10 import os
11 11 import re
12 12 import socket
13 13
14 14 from mercurial.i18n import _
15 15 from mercurial import (
16 16 encoding,
17 17 error,
18 18 pycompat,
19 19 util,
20 20 )
21 21
22 22 from . import (
23 23 common,
24 24 cvsps,
25 25 )
26 26
27 27 stringio = util.stringio
28 28 checktool = common.checktool
29 29 commit = common.commit
30 30 converter_source = common.converter_source
31 31 makedatetimestamp = common.makedatetimestamp
32 32 NoRepo = common.NoRepo
33 33
34 34 class convert_cvs(converter_source):
35 35 def __init__(self, ui, repotype, path, revs=None):
36 36 super(convert_cvs, self).__init__(ui, repotype, path, revs=revs)
37 37
38 38 cvs = os.path.join(path, "CVS")
39 39 if not os.path.exists(cvs):
40 40 raise NoRepo(_("%s does not look like a CVS checkout") % path)
41 41
42 42 checktool('cvs')
43 43
44 44 self.changeset = None
45 45 self.files = {}
46 46 self.tags = {}
47 47 self.lastbranch = {}
48 48 self.socket = None
49 49 self.cvsroot = open(os.path.join(cvs, "Root"), 'rb').read()[:-1]
50 50 self.cvsrepo = open(os.path.join(cvs, "Repository"), 'rb').read()[:-1]
51 51 self.encoding = encoding.encoding
52 52
53 53 self._connect()
54 54
55 55 def _parse(self):
56 56 if self.changeset is not None:
57 57 return
58 58 self.changeset = {}
59 59
60 60 maxrev = 0
61 61 if self.revs:
62 62 if len(self.revs) > 1:
63 63 raise error.Abort(_('cvs source does not support specifying '
64 64 'multiple revs'))
65 65 # TODO: handle tags
66 66 try:
67 67 # patchset number?
68 68 maxrev = int(self.revs[0])
69 69 except ValueError:
70 70 raise error.Abort(_('revision %s is not a patchset number')
71 71 % self.revs[0])
72 72
73 73 d = pycompat.getcwd()
74 74 try:
75 75 os.chdir(self.path)
76 76 id = None
77 77
78 78 cache = 'update'
79 79 if not self.ui.configbool('convert', 'cvsps.cache'):
80 80 cache = None
81 81 db = cvsps.createlog(self.ui, cache=cache)
82 82 db = cvsps.createchangeset(self.ui, db,
83 83 fuzz=int(self.ui.config('convert', 'cvsps.fuzz')),
84 84 mergeto=self.ui.config('convert', 'cvsps.mergeto'),
85 85 mergefrom=self.ui.config('convert', 'cvsps.mergefrom'))
86 86
87 87 for cs in db:
88 88 if maxrev and cs.id > maxrev:
89 89 break
90 90 id = str(cs.id)
91 91 cs.author = self.recode(cs.author)
92 92 self.lastbranch[cs.branch] = id
93 93 cs.comment = self.recode(cs.comment)
94 94 if self.ui.configbool('convert', 'localtimezone'):
95 95 cs.date = makedatetimestamp(cs.date[0])
96 96 date = util.datestr(cs.date, '%Y-%m-%d %H:%M:%S %1%2')
97 97 self.tags.update(dict.fromkeys(cs.tags, id))
98 98
99 99 files = {}
100 100 for f in cs.entries:
101 101 files[f.file] = "%s%s" % ('.'.join([str(x)
102 102 for x in f.revision]),
103 103 ['', '(DEAD)'][f.dead])
104 104
105 105 # add current commit to set
106 106 c = commit(author=cs.author, date=date,
107 107 parents=[str(p.id) for p in cs.parents],
108 108 desc=cs.comment, branch=cs.branch or '')
109 109 self.changeset[id] = c
110 110 self.files[id] = files
111 111
112 112 self.heads = self.lastbranch.values()
113 113 finally:
114 114 os.chdir(d)
115 115
116 116 def _connect(self):
117 117 root = self.cvsroot
118 118 conntype = None
119 119 user, host = None, None
120 120 cmd = ['cvs', 'server']
121 121
122 122 self.ui.status(_("connecting to %s\n") % root)
123 123
124 124 if root.startswith(":pserver:"):
125 125 root = root[9:]
126 126 m = re.match(r'(?:(.*?)(?::(.*?))?@)?([^:\/]*)(?::(\d*))?(.*)',
127 127 root)
128 128 if m:
129 129 conntype = "pserver"
130 130 user, passw, serv, port, root = m.groups()
131 131 if not user:
132 132 user = "anonymous"
133 133 if not port:
134 134 port = 2401
135 135 else:
136 136 port = int(port)
137 137 format0 = ":pserver:%s@%s:%s" % (user, serv, root)
138 138 format1 = ":pserver:%s@%s:%d%s" % (user, serv, port, root)
139 139
140 140 if not passw:
141 141 passw = "A"
142 142 cvspass = os.path.expanduser("~/.cvspass")
143 143 try:
144 144 pf = open(cvspass, 'rb')
145 145 for line in pf.read().splitlines():
146 146 part1, part2 = line.split(' ', 1)
147 147 # /1 :pserver:user@example.com:2401/cvsroot/foo
148 148 # Ah<Z
149 149 if part1 == '/1':
150 150 part1, part2 = part2.split(' ', 1)
151 151 format = format1
152 152 # :pserver:user@example.com:/cvsroot/foo Ah<Z
153 153 else:
154 154 format = format0
155 155 if part1 == format:
156 156 passw = part2
157 157 break
158 158 pf.close()
159 159 except IOError as inst:
160 160 if inst.errno != errno.ENOENT:
161 161 if not getattr(inst, 'filename', None):
162 162 inst.filename = cvspass
163 163 raise
164 164
165 165 sck = socket.socket()
166 166 sck.connect((serv, port))
167 167 sck.send("\n".join(["BEGIN AUTH REQUEST", root, user, passw,
168 168 "END AUTH REQUEST", ""]))
169 169 if sck.recv(128) != "I LOVE YOU\n":
170 170 raise error.Abort(_("CVS pserver authentication failed"))
171 171
172 172 self.writep = self.readp = sck.makefile('r+')
173 173
174 174 if not conntype and root.startswith(":local:"):
175 175 conntype = "local"
176 176 root = root[7:]
177 177
178 178 if not conntype:
179 179 # :ext:user@host/home/user/path/to/cvsroot
180 180 if root.startswith(":ext:"):
181 181 root = root[5:]
182 m = re.match(r'(?:([^@:/]+)@)?([^:/]+):?(.*)', root)
182 m = re.match(br'(?:([^@:/]+)@)?([^:/]+):?(.*)', root)
183 183 # Do not take Windows path "c:\foo\bar" for a connection strings
184 184 if os.path.isdir(root) or not m:
185 185 conntype = "local"
186 186 else:
187 187 conntype = "rsh"
188 188 user, host, root = m.group(1), m.group(2), m.group(3)
189 189
190 190 if conntype != "pserver":
191 191 if conntype == "rsh":
192 192 rsh = encoding.environ.get("CVS_RSH") or "ssh"
193 193 if user:
194 194 cmd = [rsh, '-l', user, host] + cmd
195 195 else:
196 196 cmd = [rsh, host] + cmd
197 197
198 198 # popen2 does not support argument lists under Windows
199 199 cmd = [util.shellquote(arg) for arg in cmd]
200 200 cmd = util.quotecommand(' '.join(cmd))
201 201 self.writep, self.readp = util.popen2(cmd)
202 202
203 203 self.realroot = root
204 204
205 205 self.writep.write("Root %s\n" % root)
206 206 self.writep.write("Valid-responses ok error Valid-requests Mode"
207 207 " M Mbinary E Checked-in Created Updated"
208 208 " Merged Removed\n")
209 209 self.writep.write("valid-requests\n")
210 210 self.writep.flush()
211 211 r = self.readp.readline()
212 212 if not r.startswith("Valid-requests"):
213 213 raise error.Abort(_('unexpected response from CVS server '
214 214 '(expected "Valid-requests", but got %r)')
215 215 % r)
216 216 if "UseUnchanged" in r:
217 217 self.writep.write("UseUnchanged\n")
218 218 self.writep.flush()
219 219 r = self.readp.readline()
220 220
221 221 def getheads(self):
222 222 self._parse()
223 223 return self.heads
224 224
225 225 def getfile(self, name, rev):
226 226
227 227 def chunkedread(fp, count):
228 228 # file-objects returned by socket.makefile() do not handle
229 229 # large read() requests very well.
230 230 chunksize = 65536
231 231 output = stringio()
232 232 while count > 0:
233 233 data = fp.read(min(count, chunksize))
234 234 if not data:
235 235 raise error.Abort(_("%d bytes missing from remote file")
236 236 % count)
237 237 count -= len(data)
238 238 output.write(data)
239 239 return output.getvalue()
240 240
241 241 self._parse()
242 242 if rev.endswith("(DEAD)"):
243 243 return None, None
244 244
245 245 args = ("-N -P -kk -r %s --" % rev).split()
246 246 args.append(self.cvsrepo + '/' + name)
247 247 for x in args:
248 248 self.writep.write("Argument %s\n" % x)
249 249 self.writep.write("Directory .\n%s\nco\n" % self.realroot)
250 250 self.writep.flush()
251 251
252 252 data = ""
253 253 mode = None
254 254 while True:
255 255 line = self.readp.readline()
256 256 if line.startswith("Created ") or line.startswith("Updated "):
257 257 self.readp.readline() # path
258 258 self.readp.readline() # entries
259 259 mode = self.readp.readline()[:-1]
260 260 count = int(self.readp.readline()[:-1])
261 261 data = chunkedread(self.readp, count)
262 262 elif line.startswith(" "):
263 263 data += line[1:]
264 264 elif line.startswith("M "):
265 265 pass
266 266 elif line.startswith("Mbinary "):
267 267 count = int(self.readp.readline()[:-1])
268 268 data = chunkedread(self.readp, count)
269 269 else:
270 270 if line == "ok\n":
271 271 if mode is None:
272 272 raise error.Abort(_('malformed response from CVS'))
273 273 return (data, "x" in mode and "x" or "")
274 274 elif line.startswith("E "):
275 275 self.ui.warn(_("cvs server: %s\n") % line[2:])
276 276 elif line.startswith("Remove"):
277 277 self.readp.readline()
278 278 else:
279 279 raise error.Abort(_("unknown CVS response: %s") % line)
280 280
281 281 def getchanges(self, rev, full):
282 282 if full:
283 283 raise error.Abort(_("convert from cvs does not support --full"))
284 284 self._parse()
285 285 return sorted(self.files[rev].iteritems()), {}, set()
286 286
287 287 def getcommit(self, rev):
288 288 self._parse()
289 289 return self.changeset[rev]
290 290
291 291 def gettags(self):
292 292 self._parse()
293 293 return self.tags
294 294
295 295 def getchangedfiles(self, rev, i):
296 296 self._parse()
297 297 return sorted(self.files[rev])
@@ -1,373 +1,373 b''
1 1 # monotone.py - monotone support for the convert extension
2 2 #
3 3 # Copyright 2008, 2009 Mikkel Fahnoe Jorgensen <mikkel@dvide.com> and
4 4 # others
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8 from __future__ import absolute_import
9 9
10 10 import os
11 11 import re
12 12
13 13 from mercurial.i18n import _
14 14 from mercurial import (
15 15 error,
16 16 pycompat,
17 17 util,
18 18 )
19 19
20 20 from . import common
21 21
22 22 class monotone_source(common.converter_source, common.commandline):
23 23 def __init__(self, ui, repotype, path=None, revs=None):
24 24 common.converter_source.__init__(self, ui, repotype, path, revs)
25 25 if revs and len(revs) > 1:
26 26 raise error.Abort(_('monotone source does not support specifying '
27 27 'multiple revs'))
28 28 common.commandline.__init__(self, ui, 'mtn')
29 29
30 30 self.ui = ui
31 31 self.path = path
32 32 self.automatestdio = False
33 33 self.revs = revs
34 34
35 35 norepo = common.NoRepo(_("%s does not look like a monotone repository")
36 36 % path)
37 37 if not os.path.exists(os.path.join(path, '_MTN')):
38 38 # Could be a monotone repository (SQLite db file)
39 39 try:
40 40 f = file(path, 'rb')
41 41 header = f.read(16)
42 42 f.close()
43 43 except IOError:
44 44 header = ''
45 45 if header != 'SQLite format 3\x00':
46 46 raise norepo
47 47
48 48 # regular expressions for parsing monotone output
49 space = r'\s*'
50 name = r'\s+"((?:\\"|[^"])*)"\s*'
49 space = br'\s*'
50 name = br'\s+"((?:\\"|[^"])*)"\s*'
51 51 value = name
52 revision = r'\s+\[(\w+)\]\s*'
53 lines = r'(?:.|\n)+'
52 revision = br'\s+\[(\w+)\]\s*'
53 lines = br'(?:.|\n)+'
54 54
55 55 self.dir_re = re.compile(space + "dir" + name)
56 56 self.file_re = re.compile(space + "file" + name +
57 57 "content" + revision)
58 58 self.add_file_re = re.compile(space + "add_file" + name +
59 59 "content" + revision)
60 60 self.patch_re = re.compile(space + "patch" + name +
61 61 "from" + revision + "to" + revision)
62 62 self.rename_re = re.compile(space + "rename" + name + "to" + name)
63 63 self.delete_re = re.compile(space + "delete" + name)
64 64 self.tag_re = re.compile(space + "tag" + name + "revision" +
65 65 revision)
66 66 self.cert_re = re.compile(lines + space + "name" + name +
67 67 "value" + value)
68 68
69 69 attr = space + "file" + lines + space + "attr" + space
70 70 self.attr_execute_re = re.compile(attr + '"mtn:execute"' +
71 71 space + '"true"')
72 72
73 73 # cached data
74 74 self.manifest_rev = None
75 75 self.manifest = None
76 76 self.files = None
77 77 self.dirs = None
78 78
79 79 common.checktool('mtn', abort=False)
80 80
81 81 def mtnrun(self, *args, **kwargs):
82 82 if self.automatestdio:
83 83 return self.mtnrunstdio(*args, **kwargs)
84 84 else:
85 85 return self.mtnrunsingle(*args, **kwargs)
86 86
87 87 def mtnrunsingle(self, *args, **kwargs):
88 88 kwargs[r'd'] = self.path
89 89 return self.run0('automate', *args, **kwargs)
90 90
91 91 def mtnrunstdio(self, *args, **kwargs):
92 92 # Prepare the command in automate stdio format
93 93 kwargs = pycompat.byteskwargs(kwargs)
94 94 command = []
95 95 for k, v in kwargs.iteritems():
96 96 command.append("%s:%s" % (len(k), k))
97 97 if v:
98 98 command.append("%s:%s" % (len(v), v))
99 99 if command:
100 100 command.insert(0, 'o')
101 101 command.append('e')
102 102
103 103 command.append('l')
104 104 for arg in args:
105 105 command += "%s:%s" % (len(arg), arg)
106 106 command.append('e')
107 107 command = ''.join(command)
108 108
109 109 self.ui.debug("mtn: sending '%s'\n" % command)
110 110 self.mtnwritefp.write(command)
111 111 self.mtnwritefp.flush()
112 112
113 113 return self.mtnstdioreadcommandoutput(command)
114 114
115 115 def mtnstdioreadpacket(self):
116 116 read = None
117 117 commandnbr = ''
118 118 while read != ':':
119 119 read = self.mtnreadfp.read(1)
120 120 if not read:
121 121 raise error.Abort(_('bad mtn packet - no end of commandnbr'))
122 122 commandnbr += read
123 123 commandnbr = commandnbr[:-1]
124 124
125 125 stream = self.mtnreadfp.read(1)
126 126 if stream not in 'mewptl':
127 127 raise error.Abort(_('bad mtn packet - bad stream type %s') % stream)
128 128
129 129 read = self.mtnreadfp.read(1)
130 130 if read != ':':
131 131 raise error.Abort(_('bad mtn packet - no divider before size'))
132 132
133 133 read = None
134 134 lengthstr = ''
135 135 while read != ':':
136 136 read = self.mtnreadfp.read(1)
137 137 if not read:
138 138 raise error.Abort(_('bad mtn packet - no end of packet size'))
139 139 lengthstr += read
140 140 try:
141 141 length = long(lengthstr[:-1])
142 142 except TypeError:
143 143 raise error.Abort(_('bad mtn packet - bad packet size %s')
144 144 % lengthstr)
145 145
146 146 read = self.mtnreadfp.read(length)
147 147 if len(read) != length:
148 148 raise error.Abort(_("bad mtn packet - unable to read full packet "
149 149 "read %s of %s") % (len(read), length))
150 150
151 151 return (commandnbr, stream, length, read)
152 152
153 153 def mtnstdioreadcommandoutput(self, command):
154 154 retval = []
155 155 while True:
156 156 commandnbr, stream, length, output = self.mtnstdioreadpacket()
157 157 self.ui.debug('mtn: read packet %s:%s:%s\n' %
158 158 (commandnbr, stream, length))
159 159
160 160 if stream == 'l':
161 161 # End of command
162 162 if output != '0':
163 163 raise error.Abort(_("mtn command '%s' returned %s") %
164 164 (command, output))
165 165 break
166 166 elif stream in 'ew':
167 167 # Error, warning output
168 168 self.ui.warn(_('%s error:\n') % self.command)
169 169 self.ui.warn(output)
170 170 elif stream == 'p':
171 171 # Progress messages
172 172 self.ui.debug('mtn: ' + output)
173 173 elif stream == 'm':
174 174 # Main stream - command output
175 175 retval.append(output)
176 176
177 177 return ''.join(retval)
178 178
179 179 def mtnloadmanifest(self, rev):
180 180 if self.manifest_rev == rev:
181 181 return
182 182 self.manifest = self.mtnrun("get_manifest_of", rev).split("\n\n")
183 183 self.manifest_rev = rev
184 184 self.files = {}
185 185 self.dirs = {}
186 186
187 187 for e in self.manifest:
188 188 m = self.file_re.match(e)
189 189 if m:
190 190 attr = ""
191 191 name = m.group(1)
192 192 node = m.group(2)
193 193 if self.attr_execute_re.match(e):
194 194 attr += "x"
195 195 self.files[name] = (node, attr)
196 196 m = self.dir_re.match(e)
197 197 if m:
198 198 self.dirs[m.group(1)] = True
199 199
200 200 def mtnisfile(self, name, rev):
201 201 # a non-file could be a directory or a deleted or renamed file
202 202 self.mtnloadmanifest(rev)
203 203 return name in self.files
204 204
205 205 def mtnisdir(self, name, rev):
206 206 self.mtnloadmanifest(rev)
207 207 return name in self.dirs
208 208
209 209 def mtngetcerts(self, rev):
210 210 certs = {"author":"<missing>", "date":"<missing>",
211 211 "changelog":"<missing>", "branch":"<missing>"}
212 212 certlist = self.mtnrun("certs", rev)
213 213 # mtn < 0.45:
214 214 # key "test@selenic.com"
215 215 # mtn >= 0.45:
216 216 # key [ff58a7ffb771907c4ff68995eada1c4da068d328]
217 217 certlist = re.split('\n\n key ["\[]', certlist)
218 218 for e in certlist:
219 219 m = self.cert_re.match(e)
220 220 if m:
221 221 name, value = m.groups()
222 222 value = value.replace(r'\"', '"')
223 223 value = value.replace(r'\\', '\\')
224 224 certs[name] = value
225 225 # Monotone may have subsecond dates: 2005-02-05T09:39:12.364306
226 226 # and all times are stored in UTC
227 227 certs["date"] = certs["date"].split('.')[0] + " UTC"
228 228 return certs
229 229
230 230 # implement the converter_source interface:
231 231
232 232 def getheads(self):
233 233 if not self.revs:
234 234 return self.mtnrun("leaves").splitlines()
235 235 else:
236 236 return self.revs
237 237
238 238 def getchanges(self, rev, full):
239 239 if full:
240 240 raise error.Abort(_("convert from monotone does not support "
241 241 "--full"))
242 242 revision = self.mtnrun("get_revision", rev).split("\n\n")
243 243 files = {}
244 244 ignoremove = {}
245 245 renameddirs = []
246 246 copies = {}
247 247 for e in revision:
248 248 m = self.add_file_re.match(e)
249 249 if m:
250 250 files[m.group(1)] = rev
251 251 ignoremove[m.group(1)] = rev
252 252 m = self.patch_re.match(e)
253 253 if m:
254 254 files[m.group(1)] = rev
255 255 # Delete/rename is handled later when the convert engine
256 256 # discovers an IOError exception from getfile,
257 257 # but only if we add the "from" file to the list of changes.
258 258 m = self.delete_re.match(e)
259 259 if m:
260 260 files[m.group(1)] = rev
261 261 m = self.rename_re.match(e)
262 262 if m:
263 263 toname = m.group(2)
264 264 fromname = m.group(1)
265 265 if self.mtnisfile(toname, rev):
266 266 ignoremove[toname] = 1
267 267 copies[toname] = fromname
268 268 files[toname] = rev
269 269 files[fromname] = rev
270 270 elif self.mtnisdir(toname, rev):
271 271 renameddirs.append((fromname, toname))
272 272
273 273 # Directory renames can be handled only once we have recorded
274 274 # all new files
275 275 for fromdir, todir in renameddirs:
276 276 renamed = {}
277 277 for tofile in self.files:
278 278 if tofile in ignoremove:
279 279 continue
280 280 if tofile.startswith(todir + '/'):
281 281 renamed[tofile] = fromdir + tofile[len(todir):]
282 282 # Avoid chained moves like:
283 283 # d1(/a) => d3/d1(/a)
284 284 # d2 => d3
285 285 ignoremove[tofile] = 1
286 286 for tofile, fromfile in renamed.items():
287 287 self.ui.debug (_("copying file in renamed directory "
288 288 "from '%s' to '%s'")
289 289 % (fromfile, tofile), '\n')
290 290 files[tofile] = rev
291 291 copies[tofile] = fromfile
292 292 for fromfile in renamed.values():
293 293 files[fromfile] = rev
294 294
295 295 return (files.items(), copies, set())
296 296
297 297 def getfile(self, name, rev):
298 298 if not self.mtnisfile(name, rev):
299 299 return None, None
300 300 try:
301 301 data = self.mtnrun("get_file_of", name, r=rev)
302 302 except Exception:
303 303 return None, None
304 304 self.mtnloadmanifest(rev)
305 305 node, attr = self.files.get(name, (None, ""))
306 306 return data, attr
307 307
308 308 def getcommit(self, rev):
309 309 extra = {}
310 310 certs = self.mtngetcerts(rev)
311 311 if certs.get('suspend') == certs["branch"]:
312 312 extra['close'] = 1
313 313 return common.commit(
314 314 author=certs["author"],
315 315 date=util.datestr(util.strdate(certs["date"], "%Y-%m-%dT%H:%M:%S")),
316 316 desc=certs["changelog"],
317 317 rev=rev,
318 318 parents=self.mtnrun("parents", rev).splitlines(),
319 319 branch=certs["branch"],
320 320 extra=extra)
321 321
322 322 def gettags(self):
323 323 tags = {}
324 324 for e in self.mtnrun("tags").split("\n\n"):
325 325 m = self.tag_re.match(e)
326 326 if m:
327 327 tags[m.group(1)] = m.group(2)
328 328 return tags
329 329
330 330 def getchangedfiles(self, rev, i):
331 331 # This function is only needed to support --filemap
332 332 # ... and we don't support that
333 333 raise NotImplementedError
334 334
335 335 def before(self):
336 336 # Check if we have a new enough version to use automate stdio
337 337 version = 0.0
338 338 try:
339 339 versionstr = self.mtnrunsingle("interface_version")
340 340 version = float(versionstr)
341 341 except Exception:
342 342 raise error.Abort(_("unable to determine mtn automate interface "
343 343 "version"))
344 344
345 345 if version >= 12.0:
346 346 self.automatestdio = True
347 347 self.ui.debug("mtn automate version %s - using automate stdio\n" %
348 348 version)
349 349
350 350 # launch the long-running automate stdio process
351 351 self.mtnwritefp, self.mtnreadfp = self._run2('automate', 'stdio',
352 352 '-d', self.path)
353 353 # read the headers
354 354 read = self.mtnreadfp.readline()
355 355 if read != 'format-version: 2\n':
356 356 raise error.Abort(_('mtn automate stdio header unexpected: %s')
357 357 % read)
358 358 while read != '\n':
359 359 read = self.mtnreadfp.readline()
360 360 if not read:
361 361 raise error.Abort(_("failed to reach end of mtn automate "
362 362 "stdio headers"))
363 363 else:
364 364 self.ui.debug("mtn automate version %s - not using automate stdio "
365 365 "(automate >= 12.0 - mtn >= 0.46 is needed)\n" % version)
366 366
367 367 def after(self):
368 368 if self.automatestdio:
369 369 self.mtnwritefp.close()
370 370 self.mtnwritefp = None
371 371 self.mtnreadfp.close()
372 372 self.mtnreadfp = None
373 373
General Comments 0
You need to be logged in to leave comments. Login now