1 # store.py - repository store handling for Mercurial |
1 # store.py - repository store handling for Mercurial) |
2 # |
2 # |
3 # Copyright 2008 Olivia Mackall <olivia@selenic.com> |
3 # Copyright 2008 Olivia Mackall <olivia@selenic.com> |
4 # |
4 # |
5 # This software may be used and distributed according to the terms of the |
5 # This software may be used and distributed according to the terms of the |
6 # GNU General Public License version 2 or any later version. |
6 # GNU General Public License version 2 or any later version. |
429 if f.endswith(REVLOG_FILES_EXT): |
432 if f.endswith(REVLOG_FILES_EXT): |
430 return True |
433 return True |
431 return False |
434 return False |
432 |
435 |
433 |
436 |
434 # the file is part of changelog data |
|
435 FILEFLAGS_CHANGELOG = 1 << 13 |
|
436 # the file is part of manifest data |
|
437 FILEFLAGS_MANIFESTLOG = 1 << 12 |
|
438 # the file is part of filelog data |
|
439 FILEFLAGS_FILELOG = 1 << 11 |
|
440 # file that are not directly part of a revlog |
|
441 FILEFLAGS_OTHER = 1 << 10 |
|
442 |
|
443 # the main entry point for a revlog |
|
444 FILEFLAGS_REVLOG_MAIN = 1 << 1 |
|
445 # a secondary file for a revlog |
|
446 FILEFLAGS_REVLOG_OTHER = 1 << 0 |
|
447 |
|
448 # files that are "volatile" and might change between listing and streaming |
|
449 FILEFLAGS_VOLATILE = 1 << 20 |
|
450 |
|
451 FILETYPE_CHANGELOG_MAIN = FILEFLAGS_CHANGELOG | FILEFLAGS_REVLOG_MAIN |
|
452 FILETYPE_CHANGELOG_OTHER = FILEFLAGS_CHANGELOG | FILEFLAGS_REVLOG_OTHER |
|
453 FILETYPE_MANIFESTLOG_MAIN = FILEFLAGS_MANIFESTLOG | FILEFLAGS_REVLOG_MAIN |
|
454 FILETYPE_MANIFESTLOG_OTHER = FILEFLAGS_MANIFESTLOG | FILEFLAGS_REVLOG_OTHER |
|
455 FILETYPE_FILELOG_MAIN = FILEFLAGS_FILELOG | FILEFLAGS_REVLOG_MAIN |
|
456 FILETYPE_FILELOG_OTHER = FILEFLAGS_FILELOG | FILEFLAGS_REVLOG_OTHER |
|
457 FILETYPE_OTHER = FILEFLAGS_OTHER |
|
458 |
|
459 |
|
460 @attr.s(slots=True) |
437 @attr.s(slots=True) |
461 class StoreFile: |
438 class StoreFile: |
462 """a file matching a store entry""" |
439 """a file matching a store entry""" |
463 |
440 |
464 unencoded_path = attr.ib() |
441 unencoded_path = attr.ib() |
584 self._details = details |
561 self._details = details |
585 self._files = None |
562 self._files = None |
586 |
563 |
587 @property |
564 @property |
588 def is_changelog(self): |
565 def is_changelog(self): |
589 return self.revlog_type & FILEFLAGS_CHANGELOG |
566 return self.revlog_type == KIND_CHANGELOG |
590 |
567 |
591 @property |
568 @property |
592 def is_manifestlog(self): |
569 def is_manifestlog(self): |
593 return self.revlog_type & FILEFLAGS_MANIFESTLOG |
570 return self.revlog_type == KIND_MANIFESTLOG |
594 |
571 |
595 @property |
572 @property |
596 def is_filelog(self): |
573 def is_filelog(self): |
597 return self.revlog_type & FILEFLAGS_FILELOG |
574 return self.revlog_type == KIND_FILELOG |
598 |
575 |
599 def main_file_path(self): |
576 def main_file_path(self): |
600 """unencoded path of the main revlog file""" |
577 """unencoded path of the main revlog file""" |
601 return self._path_prefix + b'.i' |
578 return self._path_prefix + b'.i' |
602 |
579 |
810 When [undecodable] is None, revlogs names that can't be |
787 When [undecodable] is None, revlogs names that can't be |
811 decoded cause an exception. When it is provided, it should |
788 decoded cause an exception. When it is provided, it should |
812 be a list and the filenames that can't be decoded are added |
789 be a list and the filenames that can't be decoded are added |
813 to it instead. This is very rarely needed.""" |
790 to it instead. This is very rarely needed.""" |
814 dirs = [ |
791 dirs = [ |
815 (b'data', FILEFLAGS_FILELOG, False), |
792 (b'data', KIND_FILELOG, False), |
816 (b'meta', FILEFLAGS_MANIFESTLOG, True), |
793 (b'meta', KIND_MANIFESTLOG, True), |
817 ] |
794 ] |
818 for base_dir, rl_type, strip_filename in dirs: |
795 for base_dir, rl_type, strip_filename in dirs: |
819 files = self._walk(base_dir, True, undecodable=undecodable) |
796 files = self._walk(base_dir, True, undecodable=undecodable) |
820 for revlog, details in _gather_revlog(files): |
797 for revlog, details in _gather_revlog(files): |
821 revlog_target_id = revlog.split(b'/', 1)[1] |
798 revlog_target_id = revlog.split(b'/', 1)[1] |
863 is_volatile=False, |
840 is_volatile=False, |
864 file_size=s, |
841 file_size=s, |
865 ) |
842 ) |
866 # yield manifest before changelog |
843 # yield manifest before changelog |
867 top_rl = [ |
844 top_rl = [ |
868 (manifestlogs, FILEFLAGS_MANIFESTLOG), |
845 (manifestlogs, KIND_MANIFESTLOG), |
869 (changelogs, FILEFLAGS_CHANGELOG), |
846 (changelogs, KIND_CHANGELOG), |
870 ] |
847 ] |
871 assert len(manifestlogs) <= 1 |
848 assert len(manifestlogs) <= 1 |
872 assert len(changelogs) <= 1 |
849 assert len(changelogs) <= 1 |
873 for data, revlog_type in top_rl: |
850 for data, revlog_type in top_rl: |
874 for revlog, details in sorted(data.items()): |
851 for revlog, details in sorted(data.items()): |
1157 # Mercurial. |
1134 # Mercurial. |
1158 files = ((f, None) for f in self.fncache if is_revlog_file(f)) |
1135 files = ((f, None) for f in self.fncache if is_revlog_file(f)) |
1159 by_revlog = _gather_revlog(files) |
1136 by_revlog = _gather_revlog(files) |
1160 for revlog, details in by_revlog: |
1137 for revlog, details in by_revlog: |
1161 if revlog.startswith(b'data/'): |
1138 if revlog.startswith(b'data/'): |
1162 rl_type = FILEFLAGS_FILELOG |
1139 rl_type = KIND_FILELOG |
1163 revlog_target_id = revlog.split(b'/', 1)[1] |
1140 revlog_target_id = revlog.split(b'/', 1)[1] |
1164 elif revlog.startswith(b'meta/'): |
1141 elif revlog.startswith(b'meta/'): |
1165 rl_type = FILEFLAGS_MANIFESTLOG |
1142 rl_type = KIND_MANIFESTLOG |
1166 # drop the initial directory and the `00manifest` file part |
1143 # drop the initial directory and the `00manifest` file part |
1167 tmp = revlog.split(b'/', 1)[1] |
1144 tmp = revlog.split(b'/', 1)[1] |
1168 revlog_target_id = tmp.rsplit(b'/', 1)[0] + b'/' |
1145 revlog_target_id = tmp.rsplit(b'/', 1)[0] + b'/' |
1169 else: |
1146 else: |
1170 # unreachable |
1147 # unreachable |