def fetch(self, dst_path=None, on_progress=None): if dst_path is not None and os.path.isdir(dst_path): raise TransferFailed("%r is a directory" % (dst_path,)) if dst_path: mkdir_p(os.path.dirname(dst_path)) with lock_file(dst_path) if dst_path is not None else _NULL_CTX(): if (dst_path is not None and os.path.exists(dst_path) and reasonable_get_mtime(dst_path) == self.mtime and os.path.getsize(dst_path) == self.size): return dst_path ret = None # local if self.server.uri.node == get_context().ref.uri.node: _, src_path = self.server.ask(('request-local', self.file_id)) assert _ == 'local-file' # store to specific path if dst_path is not None: if src_path != dst_path: if os.path.exists(dst_path): os.unlink(dst_path) shutil.copy(src_path, dst_path) ret = dst_path # store to temp else: fd, tmppath = tempfile.mkstemp() os.close(fd) shutil.copy(src_path, tmppath) ret = tmppath if on_progress: on_progress(fileref=self, transferred_size=self.size, local=True) # remote else: fd, tmppath = tempfile.mkstemp() os.close(fd) with open(tmppath, 'wb') as tmpfile: transferred_size = self._transfer(tmpfile, on_progress) if transferred_size != self.size: os.unlink(tmppath) raise TransferFailed("fetched file size %db does not match remote size %db" % (transferred_size, self.size)) # store to specific path if dst_path: if os.path.exists(dst_path): os.unlink(dst_path) move_or_copy(tmppath, dst_path) ret = dst_path # store to temp else: ret = tmppath os.utime(ret, (self.mtime, self.mtime)) assert reasonable_get_mtime(ret) == self.mtime return ret
def serve_file(path, abstract_path=None, node=None): mtime = reasonable_get_mtime(path) size = os.path.getsize(path) file_id = uuid.uuid4().get_hex() node = node or get_context().node server = Server._instances.get(node) if not server: server = Server._instances[node] = node.spawn(Server) server << ('serve', path, file_id) if abstract_path is None: abstract_path = os.path.basename(path) return FileRef(file_id, server, abstract_path=abstract_path, mtime=mtime, size=size)