# # # patch "mtn.py" # from [e607dd97686dc4b75de17043e7206fd686330c65] # to [5e6345494b17afba6591be6869d5f4f0b15334a9] # ============================================================ --- mtn.py e607dd97686dc4b75de17043e7206fd686330c65 +++ mtn.py 5e6345494b17afba6591be6869d5f4f0b15334a9 @@ -59,7 +59,7 @@ class Runner(object): self.database = database self.base_command = [monotone, "--db=%s" % pipes.quote(database)] -packet_header_re = re.compile(r'^(\d+):(\d+):([lm]):(\d+):') +packet_header_re = re.compile(r'^(\d+):([lm]):(\d+):') import web class Automate(Runner): @@ -92,14 +92,16 @@ class Automate(Runner): self.stop() def __process_required(self): + '''returns whether it started a process''' if self.process != None: - return + return False to_run = self.base_command + ['automate', 'stdio'] self.running_mtime = self.database_mtime() self.process = popen2.Popen3(to_run, capturestderr=True) map (set_nonblocking, [ self.process.fromchild, self.process.tochild, self.process.childerr ]) + return True def run(self, *args, **kwargs): #debug(("automate is running:", args, kwargs)) @@ -160,10 +162,27 @@ class Automate(Runner): parts.append("e") enc = ''.join(parts) + def read_header(): + buffer = "" + while True: + r_stdin, r_stdout, r_stderr = select.select([self.process.fromchild], [], [], None) + if not r_stdin and not r_stdout and not r_stderr: + break + if self.process.fromchild in r_stdin: + data = self.process.fromchild.read() + if data == "": + break + buffer += data + # fixme: shouldn't be hardcoded, at least not here + if buffer == "format-version: 2\n\n": + break + # number of tries to get a working mtn going.. for i in xrange(2): - self.__process_required() + isNew = self.__process_required() try: + if isNew: + read_header() self.process.tochild.write(enc) self.process.tochild.flush() break @@ -193,8 +212,7 @@ class Automate(Runner): if not m: break in_packet = True - cmdnum, errnum, pstate, length = m.groups() - errnum = int(errnum) + cmdnum, pstate, length = m.groups() length = int(length) header_length = m.end(m.lastindex) + 1 # the '1' is the colon @@ -206,18 +224,18 @@ class Automate(Runner): buffer = buffer[header_length+length:] complete = pstate == 'l' in_packet = False - yield errnum, complete, result + yield complete, result if complete: break # get our response, and yield() it back one line at a time - code_max = -1 data_buf = '' - for code, is_last, data in read_result_packets(): - if code and code > code_max: - code_max = code - data_buf += data + for is_last, data in read_result_packets(): + if is_last: + code = int(data) + else: + data_buf += data while True: nl_idx = data_buf.find('\n') if nl_idx == -1: @@ -227,8 +245,8 @@ class Automate(Runner): # left over data? if data_buf: yield data_buf - if code_max > 0: - raise MonotoneException("error code %d in automate packet." % (code_max)) + if code > 0: + raise MonotoneException("error code %d in automate packet." % (code)) class Standalone(Runner): """Runs commands by running monotone. One monotone process