def read_lump(self): self._finish_last_lump() self.current_lump = SvnLump() self._read_headers() if not self.current_lump.get_header_keys(): return None self._read_properties() self._create_content_tin() return self.current_lump
def get_path_from_target(self, kind, path, action, from_path, from_rev): assert kind == 'file' or kind == 'dir' assert action == 'add' or action == 'replace' lump = SvnLump() lump.set_header('Node-path', path) lump.set_header('Node-kind', kind) lump.set_header('Node-action', action) lump.set_header('Node-copyfrom-path', from_path) lump.set_header('Node-copyfrom-rev', str(from_rev)) self.dump_writer.write_lump(lump)
def revision_header(self, rev, log_message=None): lump = SvnLump() lump.set_header('Revision-number', str(rev)) rev_info = self.source_repository.get_revision_info(rev) if log_message: new_log_message = log_message else: new_log_message = rev_info.log_message lump.properties = { 'svn:author': rev_info.author, 'svn:date': rev_info.date, 'svn:log': new_log_message } self.dump_writer.write_lump(lump)
def get_path_from_target(self, kind, path, action, from_path, from_rev): assert kind == 'file' or kind =='dir' assert action == 'add' or action =='replace' lump = SvnLump() lump.set_header('Node-path', path) lump.set_header('Node-kind', kind) lump.set_header('Node-action', action) lump.set_header('Node-copyfrom-path', from_path) lump.set_header('Node-copyfrom-rev', str(from_rev)) self.dump_writer.write_lump(lump)
def dump_header_lumps(self): lump = SvnLump() lump.set_header('SVN-fs-dump-format-version', '2') self.dump_writer.write_lump(lump) lump = SvnLump() lump.set_header('UUID', str(self.source_repository.get_uuid())) self.dump_writer.write_lump(lump)
class SvnDumpReader(object): def __init__(self, file_handle): self.file_handle = file_handle self.current_lump = None def read_lump(self): self._finish_last_lump() self.current_lump = SvnLump() self._read_headers() if not self.current_lump.get_header_keys(): return None self._read_properties() self._create_content_tin() return self.current_lump def _finish_last_lump(self): # Ensure that ContentTin of last lump gets depleted if self.current_lump and self.current_lump.content: self.current_lump.content.discard() def _read_headers(self): fh = self.file_handle header_count = 0 while True: line = fh.readline() if not line: if header_count > 0: raise Exception("Found End of file before end of headers!") return if line == "\n": if header_count > 0: return else: m = match("(.+): (.*)$", line) if not m: raise Exception("Found broken header line:\n" + line) self.current_lump.set_header(m.group(1), m.group(2)) header_count += 1 def _read_properties(self): lump = self.current_lump if not lump.has_header('Prop-content-length'): return expected_length = int(lump.get_header('Prop-content-length')) actual_length = 0 while True: ( key, key_length ) = self._read_prop_key_and_length() actual_length += key_length if key is None: break; ( value, value_length ) = self._read_prop_value_and_length() actual_length += value_length lump.properties[key] = value if actual_length != expected_length: raise Exception( "PROPS section should be %d bytes long but was %d!" % ( expected_length, actual_length ) ) def _read_prop_key_and_length(self): fh = self.file_handle line = fh.readline() length = len(line) if line == 'PROPS-END\n': return ( None, length ) if not line.startswith('K '): raise Exception("Needed key size line (K <number>) but got:\n" + line) size = int(line[2:-1]) ( key, key_length ) = self._read_field_of_given_size_and_length(size) length += key_length return ( key, length ) def _read_prop_value_and_length(self): fh = self.file_handle line = fh.readline() length = len(line) if not line.startswith('V '): raise Exception("Needed value size line (V <number>) but got:\n" + line) size = int(line[2:-1]) ( value, value_length ) = self._read_field_of_given_size_and_length(size) length += value_length return ( value, length ) def _read_field_of_given_size_and_length(self, size): lines = [ ] length = 0 while True: line = self.file_handle.readline() if not line: raise Exception("Reached end-of-file while reading field!") lines.append(line) length += len(line) if length == size+1: return ( join(lines, '')[0:-1], length ) elif length > size+1: raise Exception("Field length did not match expected size!") def _create_content_tin(self): lump = self.current_lump if not lump.has_header('Text-content-length'): return size = int(lump.get_header('Text-content-length')) md5sum = None if lump.has_header('Text-content-md5'): md5sum = lump.get_header('Text-content-md5') lump.content = ContentTin(self.file_handle, size, md5sum)
def get_node_from_source(self, kind, path, action, from_path, from_rev): assert kind == 'file' or kind == 'dir' assert action == 'add' or action =='replace' if self._is_obsolete_tag_or_branch_copy(path, from_rev): self._handle_obsolete_tag_or_branch(path) return path = normpath(path) repo = self.source_repository lump = SvnLump() lump.set_header('Node-path', path) lump.set_header('Node-kind', kind) lump.set_header('Node-action', action) if kind == 'file': tin = repo.get_tin_for_file(from_path, from_rev) lump.content = tin lump.set_header('Text-content-length', str(tin.size)) lump.set_header('Text-content-md5', tin.md5sum) lump.properties = repo.get_properties_of_path(from_path, from_rev) self.dump_writer.write_lump(lump)
def mkdir(self, path): lump = SvnLump() lump.set_header('Node-path', normpath(path)) lump.set_header('Node-kind', 'dir') lump.set_header('Node-action', 'add') self.dump_writer.write_lump(lump)
def delete_path(self, path): lump = SvnLump() lump.set_header('Node-path', normpath(path)) lump.set_header('Node-action', 'delete') self.dump_writer.write_lump(lump)
def get_node_from_source(self, kind, path, action, from_path, from_rev): assert kind == 'file' or kind == 'dir' assert action == 'add' or action == 'replace' if self._is_obsolete_tag_or_branch_copy(path, from_rev): self._handle_obsolete_tag_or_branch(path) return path = normpath(path) repo = self.source_repository lump = SvnLump() lump.set_header('Node-path', path) lump.set_header('Node-kind', kind) lump.set_header('Node-action', action) if kind == 'file': tin = repo.get_tin_for_file(from_path, from_rev) lump.content = tin lump.set_header('Text-content-length', str(tin.size)) lump.set_header('Text-content-md5', tin.md5sum) lump.properties = repo.get_properties_of_path(from_path, from_rev) self.dump_writer.write_lump(lump)
class SvnDumpReader(object): def __init__(self, file_handle): self.file_handle = file_handle self.current_lump = None def read_lump(self): self._finish_last_lump() self.current_lump = SvnLump() self._read_headers() if not self.current_lump.get_header_keys(): return None self._read_properties() self._create_content_tin() return self.current_lump def _finish_last_lump(self): # Ensure that ContentTin of last lump gets depleted if self.current_lump and self.current_lump.content: self.current_lump.content.discard() def _read_headers(self): fh = self.file_handle header_count = 0 while True: line = fh.readline() if not line: if header_count > 0: raise Exception("Found End of file before end of headers!") return if line == "\n": if header_count > 0: return else: m = match("(.+): (.*)$", line) if not m: raise Exception("Found broken header line:\n" + line) self.current_lump.set_header(m.group(1), m.group(2)) header_count += 1 def _read_properties(self): lump = self.current_lump if not lump.has_header('Prop-content-length'): return expected_length = int(lump.get_header('Prop-content-length')) actual_length = 0 while True: (key, key_length) = self._read_prop_key_and_length() actual_length += key_length if key is None: break (value, value_length) = self._read_prop_value_and_length() actual_length += value_length lump.properties[key] = value if actual_length != expected_length: raise Exception( "PROPS section should be %d bytes long but was %d!" % (expected_length, actual_length)) def _read_prop_key_and_length(self): fh = self.file_handle line = fh.readline() length = len(line) if line == 'PROPS-END\n': return (None, length) if not line.startswith('K '): raise Exception("Needed key size line (K <number>) but got:\n" + line) size = int(line[2:-1]) (key, key_length) = self._read_field_of_given_size_and_length(size) length += key_length return (key, length) def _read_prop_value_and_length(self): fh = self.file_handle line = fh.readline() length = len(line) if not line.startswith('V '): raise Exception("Needed value size line (V <number>) but got:\n" + line) size = int(line[2:-1]) (value, value_length) = self._read_field_of_given_size_and_length(size) length += value_length return (value, length) def _read_field_of_given_size_and_length(self, size): lines = [] length = 0 while True: line = self.file_handle.readline() if not line: raise Exception("Reached end-of-file while reading field!") lines.append(line) length += len(line) if length == size + 1: return (join(lines, '')[0:-1], length) elif length > size + 1: raise Exception("Field length did not match expected size!") def _create_content_tin(self): lump = self.current_lump if not lump.has_header('Text-content-length'): return size = int(lump.get_header('Text-content-length')) md5sum = None if lump.has_header('Text-content-md5'): md5sum = lump.get_header('Text-content-md5') lump.content = ContentTin(self.file_handle, size, md5sum)