comparison mercurial/store.py @ 50639:5e60abf811f3

stream-clone: make it the responsability of the store entry to stream content The store entry has more context, this will especially be true when it comes to revlogs. So we move the details of how to retrieve binary content to the StoreEntry. The stream clone code now focus on the protocol bits.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Sun, 28 May 2023 05:52:58 +0200
parents 8fc10bfd9887
children 9caa860dcbec
comparison
equal deleted inserted replaced
50638:8fc10bfd9887 50639:5e60abf811f3
467 _file_size = attr.ib(default=None) 467 _file_size = attr.ib(default=None)
468 is_volatile = attr.ib(default=False) 468 is_volatile = attr.ib(default=False)
469 469
470 def file_size(self, vfs): 470 def file_size(self, vfs):
471 if self._file_size is None: 471 if self._file_size is None:
472 if vfs is None:
473 msg = b"calling vfs-less file_size without prior call: %s"
474 msg %= self.unencoded_path
475 raise error.ProgrammingError(msg)
472 try: 476 try:
473 self._file_size = vfs.stat(self.unencoded_path).st_size 477 self._file_size = vfs.stat(self.unencoded_path).st_size
474 except FileNotFoundError: 478 except FileNotFoundError:
475 self._file_size = 0 479 self._file_size = 0
476 return self._file_size 480 return self._file_size
477 481
482 def get_stream(self, vfs, copies):
483 """return data "stream" information for this file
484
485 (unencoded_file_path, content_iterator, content_size)
486 """
487 size = self.file_size(None)
488
489 def get_stream():
490 actual_path = copies[vfs.join(self.unencoded_path)]
491 with open(actual_path, 'rb') as fp:
492 yield None # ready to stream
493 if size <= 65536:
494 yield fp.read(size)
495 else:
496 yield from util.filechunkiter(fp, limit=size)
497
498 s = get_stream()
499 next(s)
500 return (self.unencoded_path, s, size)
501
478 502
479 @attr.s(slots=True, init=False) 503 @attr.s(slots=True, init=False)
480 class BaseStoreEntry: 504 class BaseStoreEntry:
481 """An entry in the store 505 """An entry in the store
482 506
483 This is returned by `store.walk` and represent some data in the store.""" 507 This is returned by `store.walk` and represent some data in the store."""
484 508
485 def files(self) -> List[StoreFile]: 509 def files(self) -> List[StoreFile]:
486 raise NotImplementedError 510 raise NotImplementedError
511
512 def get_streams(self, vfs, copies=None):
513 """return a list of data stream associated to files for this entry
514
515 return [(unencoded_file_path, content_iterator, content_size), …]
516 """
517 assert vfs is not None
518 return [f.get_stream(vfs, copies) for f in self.files()]
487 519
488 520
489 @attr.s(slots=True, init=False) 521 @attr.s(slots=True, init=False)
490 class SimpleStoreEntry(BaseStoreEntry): 522 class SimpleStoreEntry(BaseStoreEntry):
491 """A generic entry in the store""" 523 """A generic entry in the store"""