# # patch "TODO" # from [cf0d5dc2493d53cf6ae94759cb0da5639de3e8cb] # to [4c1f53a98bd124401e02f0009de48a780b77b2b5] # # patch "dumb.py" # from [b520c982593c8711ef22e447b7084ee0a7ea7171] # to [3366d2e3486074868b7dd886f5fd436e7b88c30b] # # patch "fs.py" # from [65c47ed1a28915fa5fccf7abf5e16ac240dd99a0] # to [7db22b570330d6be8190323f9a3af6333e458aa7] # # patch "merkle_dir.py" # from [d4e89ce8e256741fd064a9694d06026e341c5b84] # to [1ed46dcbd03429fb73b53090b6fd291c325972f5] # ======================================================================== --- TODO cf0d5dc2493d53cf6ae94759cb0da5639de3e8cb +++ TODO 4c1f53a98bd124401e02f0009de48a780b77b2b5 @@ -1,7 +1,8 @@ * packet commands -> automate? * merkle dir stuff that doesn't require loading entire chunks into memory all the time * ftp/sftp/http + - with pipelining * possibly better rollback stuff? - e.g., truncate when possible - include some info in the lockdir on who has things locked, to aid ======================================================================== --- dumb.py b520c982593c8711ef22e447b7084ee0a7ea7171 +++ dumb.py 3366d2e3486074868b7dd886f5fd436e7b88c30b @@ -1,25 +1,33 @@ import sha from sets import Set import os import os.path from cStringIO import StringIO +import merkle_dir +import fs +import zlib -def do_import(monotone, dir): +def do_full_import(monotone, url): monotone.ensure_db() - md = MerkleDir(dir) - monotone.feed(md.chunks()) + md = merkle_dir.MerkleDir(fs.readable_fs_for_url(url)) + def all_data(): + for id, data in md.all_chunks(): + yield zlib.decompress(data) + monotone.feed(all_data()) -def do_export(monotone, dir): - md = MerkleDir(dir) +def do_export(monotone, url): + md = merkle_dir.MerkleDir(fs.writeable_fs_for_url(url)) + md.begin() + curr_ids = Set(md.all_ids()) for rid in monotone.toposort(monotone.revisions_list()): certs = monotone.get_cert_packets(rid) for cert in certs: - handle = md.add(sha.new(cert).hexdigest()) - if handle: - handle.write(cert) - handle.close() - handle = md.add(rid) - if handle: + id = sha.new(cert).hexdigest() + if id not in curr_ids: + data = zlib.compress(cert) + md.add(id, data) + if rid not in curr_ids: + rdata = StringIO() revision_text = monotone.get_revision(rid) revision_parsed = monotone.basic_io_parser(revision_text) new_manifest = None @@ -40,17 +48,15 @@ if old_fid: new_files[new_fid] = old_fid - handle.write(monotone.get_revision_packet(rid)) + rdata.write(monotone.get_revision_packet(rid)) if old_manifest: - handle.write(monotone.get_manifest_delta_packet(old_manifest, new_manifest)) + rdata.write(monotone.get_manifest_delta_packet(old_manifest, new_manifest)) else: - handle.write(monotone.get_manifest_packet(new_manifest)) + rdata.write(monotone.get_manifest_packet(new_manifest)) for new_fid, old_fid in new_files.items(): if old_fid: - handle.write(monotone.get_file_delta_packet(old_fid, new_fid)) + rdata.write(monotone.get_file_delta_packet(old_fid, new_fid)) else: + rdata.write(monotone.get_file_packet(new_fid)) + md.add(rid, zlib.compress(rdata.getvalue())) + md.commit() - handle.write(monotone.get_file_packet(new_fid)) - handle.close() - - md.rehash() - ======================================================================== --- fs.py 65c47ed1a28915fa5fccf7abf5e16ac240dd99a0 +++ fs.py 7db22b570330d6be8190323f9a3af6333e458aa7 @@ -1,8 +1,14 @@ # interface to FS-like things import os import os.path +def readable_fs_for_url(url): + return LocalReadableFS(url) + +def writeable_fs_for_url(url): + return LocalWriteableFs(url) + class ReadableFS: # All operators are blocking @@ -33,17 +39,19 @@ def exists(self, filename): raise NotImplementedError - # Must return 0 for non-existent files - def size(self, filename): - raise NotImplementedError - class WriteableFS (ReadableFS): # returns an object that supports write(), flush(), close() with standard # file object semantics def open_append(self, filename): raise NotImplementedError + # Must return 0 for non-existent files + # you might think this was a ReadableFS sort of thing, except that it's + # only used in conjunction with open_append. + def size(self, filename): + raise NotImplementedError + # files is a map {filename -> contents of file} # this operation must be atomic and clobbering def put(self, files): ======================================================================== --- merkle_dir.py d4e89ce8e256741fd064a9694d06026e341c5b84 +++ merkle_dir.py 1ed46dcbd03429fb73b53090b6fd291c325972f5 @@ -309,6 +309,10 @@ def all_chunks(self): return self.get_chunks(self._all_chunk_locations()) + def all_ids(self): + for id, location in self._all_chunk_locations(): + yield id + # id_locations is an iterable over (id, location) tuples # yields (id, data) tuples def get_chunks(self, id_locations):