mercurial/store.py
changeset 50496 e50d1fe7ebb4
parent 50495 ed8cda1c18e1
child 50497 66c556968222
equal deleted inserted replaced
50495:ed8cda1c18e1 50496:e50d1fe7ebb4
   462 class BaseStoreEntry:
   462 class BaseStoreEntry:
   463     """An entry in the store
   463     """An entry in the store
   464 
   464 
   465     This is returned by `store.walk` and represent some data in the store."""
   465     This is returned by `store.walk` and represent some data in the store."""
   466 
   466 
       
   467 
       
   468 @attr.s(slots=True, init=False)
       
   469 class SimpleStoreEntry(BaseStoreEntry):
       
   470     """A generic entry in the store"""
       
   471 
       
   472     is_revlog = False
       
   473 
   467     _entry_path = attr.ib()
   474     _entry_path = attr.ib()
   468     _is_volatile = attr.ib(default=False)
   475     _is_volatile = attr.ib(default=False)
   469     _file_size = attr.ib(default=None)
   476     _file_size = attr.ib(default=None)
   470 
   477 
   471     def __init__(
   478     def __init__(
   472         self,
   479         self,
   473         entry_path,
   480         entry_path,
   474         is_volatile=False,
   481         is_volatile=False,
   475         file_size=None,
   482         file_size=None,
   476     ):
   483     ):
       
   484         super().__init__()
   477         self._entry_path = entry_path
   485         self._entry_path = entry_path
   478         self._is_volatile = is_volatile
   486         self._is_volatile = is_volatile
   479         self._file_size = file_size
   487         self._file_size = file_size
   480 
   488 
   481     def files(self):
   489     def files(self):
   487             )
   495             )
   488         ]
   496         ]
   489 
   497 
   490 
   498 
   491 @attr.s(slots=True, init=False)
   499 @attr.s(slots=True, init=False)
   492 class SimpleStoreEntry(BaseStoreEntry):
       
   493     """A generic entry in the store"""
       
   494 
       
   495     is_revlog = False
       
   496 
       
   497 
       
   498 @attr.s(slots=True, init=False)
       
   499 class RevlogStoreEntry(BaseStoreEntry):
   500 class RevlogStoreEntry(BaseStoreEntry):
   500     """A revlog entry in the store"""
   501     """A revlog entry in the store"""
   501 
   502 
   502     is_revlog = True
   503     is_revlog = True
       
   504 
   503     revlog_type = attr.ib(default=None)
   505     revlog_type = attr.ib(default=None)
   504     target_id = attr.ib(default=None)
   506     target_id = attr.ib(default=None)
   505     is_revlog_main = attr.ib(default=None)
   507     _path_prefix = attr.ib(default=None)
       
   508     _details = attr.ib(default=None)
   506 
   509 
   507     def __init__(
   510     def __init__(
   508         self,
   511         self,
   509         entry_path,
       
   510         revlog_type,
   512         revlog_type,
       
   513         path_prefix,
   511         target_id,
   514         target_id,
   512         is_revlog_main=False,
   515         details,
   513         is_volatile=False,
       
   514         file_size=None,
       
   515     ):
   516     ):
   516         super().__init__(
   517         super().__init__()
   517             entry_path=entry_path,
       
   518             is_volatile=is_volatile,
       
   519             file_size=file_size,
       
   520         )
       
   521         self.revlog_type = revlog_type
   518         self.revlog_type = revlog_type
   522         self.target_id = target_id
   519         self.target_id = target_id
   523         self.is_revlog_main = is_revlog_main
   520         self._path_prefix = path_prefix
       
   521         assert b'.i' in details, (path_prefix, details)
       
   522         self._details = details
   524 
   523 
   525     def main_file_path(self):
   524     def main_file_path(self):
   526         """unencoded path of the main revlog file"""
   525         """unencoded path of the main revlog file"""
   527         return self._entry_path
   526         return self._path_prefix + b'.i'
       
   527 
       
   528     def files(self):
       
   529         files = []
       
   530         for ext in sorted(self._details, key=_ext_key):
       
   531             path = self._path_prefix + ext
       
   532             data = self._details[ext]
       
   533             files.append(StoreFile(unencoded_path=path, **data))
       
   534         return files
   528 
   535 
   529 
   536 
   530 @attr.s(slots=True)
   537 @attr.s(slots=True)
   531 class StoreFile:
   538 class StoreFile:
   532     """a file matching an entry"""
   539     """a file matching an entry"""
   533 
   540 
   534     unencoded_path = attr.ib()
   541     unencoded_path = attr.ib()
   535     _file_size = attr.ib(default=False)
   542     _file_size = attr.ib(default=None)
   536     is_volatile = attr.ib(default=False)
   543     is_volatile = attr.ib(default=False)
   537 
   544 
   538     def file_size(self, vfs):
   545     def file_size(self, vfs):
   539         if self._file_size is not None:
   546         if self._file_size is not None:
   540             return self._file_size
   547             return self._file_size
   650         ]
   657         ]
   651         for base_dir, rl_type in dirs:
   658         for base_dir, rl_type in dirs:
   652             files = self._walk(base_dir, True, undecodable=undecodable)
   659             files = self._walk(base_dir, True, undecodable=undecodable)
   653             files = (f for f in files if f[1][0] is not None)
   660             files = (f for f in files if f[1][0] is not None)
   654             for revlog, details in _gather_revlog(files):
   661             for revlog, details in _gather_revlog(files):
       
   662                 file_details = {}
       
   663                 revlog_target_id = revlog.split(b'/', 1)[1]
   655                 for ext, (t, s) in sorted(details.items()):
   664                 for ext, (t, s) in sorted(details.items()):
   656                     u = revlog + ext
   665                     file_details[ext] = {
   657                     revlog_target_id = revlog.split(b'/', 1)[1]
   666                         'is_volatile': bool(t & FILEFLAGS_VOLATILE),
   658                     yield RevlogStoreEntry(
   667                         'file_size': s,
   659                         entry_path=u,
   668                     }
   660                         revlog_type=rl_type,
   669                 yield RevlogStoreEntry(
   661                         target_id=revlog_target_id,
   670                     path_prefix=revlog,
   662                         is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN),
   671                     revlog_type=rl_type,
   663                         is_volatile=bool(t & FILEFLAGS_VOLATILE),
   672                     target_id=revlog_target_id,
   664                         file_size=s,
   673                     details=file_details,
   665                     )
   674                 )
   666 
   675 
   667     def topfiles(self) -> Generator[BaseStoreEntry, None, None]:
   676     def topfiles(self) -> Generator[BaseStoreEntry, None, None]:
   668         files = reversed(self._walk(b'', False))
   677         files = reversed(self._walk(b'', False))
   669 
   678 
   670         changelogs = collections.defaultdict(dict)
   679         changelogs = collections.defaultdict(dict)
   690         ]
   699         ]
   691         assert len(manifestlogs) <= 1
   700         assert len(manifestlogs) <= 1
   692         assert len(changelogs) <= 1
   701         assert len(changelogs) <= 1
   693         for data, revlog_type in top_rl:
   702         for data, revlog_type in top_rl:
   694             for revlog, details in sorted(data.items()):
   703             for revlog, details in sorted(data.items()):
   695                 # (keeping ordering so we get 00changelog.i last)
   704                 file_details = {}
   696                 key = lambda x: _ext_key(x[0])
   705                 for ext, (t, s) in details.items():
   697                 for ext, (t, s) in sorted(details.items(), key=key):
   706                     file_details[ext] = {
   698                     u = revlog + ext
   707                         'is_volatile': bool(t & FILEFLAGS_VOLATILE),
   699                     yield RevlogStoreEntry(
   708                         'file_size': s,
   700                         entry_path=u,
   709                     }
   701                         revlog_type=revlog_type,
   710                 yield RevlogStoreEntry(
   702                         target_id=b'',
   711                     path_prefix=revlog,
   703                         is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN),
   712                     revlog_type=revlog_type,
   704                         is_volatile=bool(t & FILEFLAGS_VOLATILE),
   713                     target_id=b'',
   705                         file_size=s,
   714                     details=file_details,
   706                     )
   715                 )
   707 
   716 
   708     def walk(self, matcher=None) -> Generator[BaseStoreEntry, None, None]:
   717     def walk(self, matcher=None) -> Generator[BaseStoreEntry, None, None]:
   709         """return files related to data storage (ie: revlogs)
   718         """return files related to data storage (ie: revlogs)
   710 
   719 
   711         yields (file_type, unencoded, size)
   720         yields (file_type, unencoded, size)
   979         # fncache might contains such file added by previous version of
   988         # fncache might contains such file added by previous version of
   980         # Mercurial.
   989         # Mercurial.
   981         files = (f for f in files if f[1] is not None)
   990         files = (f for f in files if f[1] is not None)
   982         by_revlog = _gather_revlog(files)
   991         by_revlog = _gather_revlog(files)
   983         for revlog, details in by_revlog:
   992         for revlog, details in by_revlog:
       
   993             file_details = {}
   984             if revlog.startswith(b'data/'):
   994             if revlog.startswith(b'data/'):
   985                 rl_type = FILEFLAGS_FILELOG
   995                 rl_type = FILEFLAGS_FILELOG
   986                 revlog_target_id = revlog.split(b'/', 1)[1]
   996                 revlog_target_id = revlog.split(b'/', 1)[1]
   987             elif revlog.startswith(b'meta/'):
   997             elif revlog.startswith(b'meta/'):
   988                 rl_type = FILEFLAGS_MANIFESTLOG
   998                 rl_type = FILEFLAGS_MANIFESTLOG
   990                 tmp = revlog.split(b'/', 1)[1]
  1000                 tmp = revlog.split(b'/', 1)[1]
   991                 revlog_target_id = tmp.rsplit(b'/', 1)[0] + b'/'
  1001                 revlog_target_id = tmp.rsplit(b'/', 1)[0] + b'/'
   992             else:
  1002             else:
   993                 # unreachable
  1003                 # unreachable
   994                 assert False, revlog
  1004                 assert False, revlog
   995             for ext, t in sorted(details.items()):
  1005             for ext, t in details.items():
   996                 f = revlog + ext
  1006                 file_details[ext] = {
   997                 entry = RevlogStoreEntry(
  1007                     'is_volatile': bool(t & FILEFLAGS_VOLATILE),
   998                     entry_path=f,
  1008                 }
   999                     revlog_type=rl_type,
  1009             entry = RevlogStoreEntry(
  1000                     target_id=revlog_target_id,
  1010                 path_prefix=revlog,
  1001                     is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN),
  1011                 revlog_type=rl_type,
  1002                     is_volatile=bool(t & FILEFLAGS_VOLATILE),
  1012                 target_id=revlog_target_id,
  1003                 )
  1013                 details=file_details,
  1004                 if _match_tracked_entry(entry, matcher):
  1014             )
  1005                     yield entry
  1015             if _match_tracked_entry(entry, matcher):
       
  1016                 yield entry
  1006 
  1017 
  1007     def copylist(self):
  1018     def copylist(self):
  1008         d = (
  1019         d = (
  1009             b'bookmarks',
  1020             b'bookmarks',
  1010             b'narrowspec',
  1021             b'narrowspec',