diff -r 8fc10bfd9887 -r 5e60abf811f3 mercurial/store.py --- a/mercurial/store.py Mon May 29 11:42:16 2023 +0200 +++ b/mercurial/store.py Sun May 28 05:52:58 2023 +0200 @@ -469,12 +469,36 @@ def file_size(self, vfs): if self._file_size is None: + if vfs is None: + msg = b"calling vfs-less file_size without prior call: %s" + msg %= self.unencoded_path + raise error.ProgrammingError(msg) try: self._file_size = vfs.stat(self.unencoded_path).st_size except FileNotFoundError: self._file_size = 0 return self._file_size + def get_stream(self, vfs, copies): + """return data "stream" information for this file + + (unencoded_file_path, content_iterator, content_size) + """ + size = self.file_size(None) + + def get_stream(): + actual_path = copies[vfs.join(self.unencoded_path)] + with open(actual_path, 'rb') as fp: + yield None # ready to stream + if size <= 65536: + yield fp.read(size) + else: + yield from util.filechunkiter(fp, limit=size) + + s = get_stream() + next(s) + return (self.unencoded_path, s, size) + @attr.s(slots=True, init=False) class BaseStoreEntry: @@ -485,6 +509,14 @@ def files(self) -> List[StoreFile]: raise NotImplementedError + def get_streams(self, vfs, copies=None): + """return a list of data stream associated to files for this entry + + return [(unencoded_file_path, content_iterator, content_size), …] + """ + assert vfs is not None + return [f.get_stream(vfs, copies) for f in self.files()] + @attr.s(slots=True, init=False) class SimpleStoreEntry(BaseStoreEntry):