17 converter_source.__init__(self, ui, path, rev) |
17 converter_source.__init__(self, ui, path, rev) |
18 commandline.__init__(self, ui, 'mtn') |
18 commandline.__init__(self, ui, 'mtn') |
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) |
25 if not os.path.exists(os.path.join(path, '_MTN')): |
26 if not os.path.exists(os.path.join(path, '_MTN')): |
26 # Could be a monotone repository (SQLite db file) |
27 # Could be a monotone repository (SQLite db file) |
71 except: |
72 except: |
72 raise norepo |
73 raise norepo |
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) |
|
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 |
78 |
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 |
82 self.manifest = self.mtnrun("get_manifest_of", rev).split("\n\n") |
176 self.manifest = self.mtnrun("get_manifest_of", rev).split("\n\n") |
223 |
317 |
224 def getchangedfiles(self, rev, i): |
318 def getchangedfiles(self, rev, i): |
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 |