Show More
@@ -552,7 +552,8 b' def unixpath(path):' | |||||
552 | def islfilesrepo(repo): |
|
552 | def islfilesrepo(repo): | |
553 | '''Return true if the repo is a largefile repo.''' |
|
553 | '''Return true if the repo is a largefile repo.''' | |
554 | if b'largefiles' in repo.requirements and any( |
|
554 | if b'largefiles' in repo.requirements and any( | |
555 | shortnameslash in f[1] for f in repo.store.datafiles() |
|
555 | shortnameslash in entry.unencoded_path | |
|
556 | for entry in repo.store.datafiles() | |||
556 | ): |
|
557 | ): | |
557 | return True |
|
558 | return True | |
558 |
|
559 |
@@ -458,7 +458,8 b' def reposetup(ui, repo):' | |||||
458 | def checkrequireslfiles(ui, repo, **kwargs): |
|
458 | def checkrequireslfiles(ui, repo, **kwargs): | |
459 | with repo.lock(): |
|
459 | with repo.lock(): | |
460 | if b'largefiles' not in repo.requirements and any( |
|
460 | if b'largefiles' not in repo.requirements and any( | |
461 |
lfutil.shortname + b'/' in |
|
461 | lfutil.shortname + b'/' in entry.unencoded_path | |
|
462 | for entry in repo.store.datafiles() | |||
462 | ): |
|
463 | ): | |
463 | repo.requirements.add(b'largefiles') |
|
464 | repo.requirements.add(b'largefiles') | |
464 | scmutil.writereporequirements(repo) |
|
465 | scmutil.writereporequirements(repo) |
@@ -288,7 +288,8 b' def _narrow(' | |||||
288 | repair.strip(ui, unfi, tostrip, topic=b'narrow', backup=backup) |
|
288 | repair.strip(ui, unfi, tostrip, topic=b'narrow', backup=backup) | |
289 |
|
289 | |||
290 | todelete = [] |
|
290 | todelete = [] | |
291 |
for |
|
291 | for entry in repo.store.datafiles(): | |
|
292 | f = entry.unencoded_path | |||
292 | if f.startswith(b'data/'): |
|
293 | if f.startswith(b'data/'): | |
293 | file = f[5:-2] |
|
294 | file = f[5:-2] | |
294 | if not newmatch(file): |
|
295 | if not newmatch(file): |
@@ -162,25 +162,34 b' def onetimesetup(ui):' | |||||
162 | ): |
|
162 | ): | |
163 | n = util.pconvert(fp[striplen:]) |
|
163 | n = util.pconvert(fp[striplen:]) | |
164 | d = store.decodedir(n) |
|
164 | d = store.decodedir(n) | |
165 |
|
|
165 | yield store.StoreEntry( | |
166 |
|
|
166 | unencoded_path=d, | |
|
167 | is_revlog=True, | |||
|
168 | revlog_type=None, | |||
|
169 | is_revlog_main=False, | |||
|
170 | is_volatile=False, | |||
|
171 | file_size=st.st_size, | |||
|
172 | ) | |||
|
173 | ||||
167 | if kind == stat.S_IFDIR: |
|
174 | if kind == stat.S_IFDIR: | |
168 | visit.append(fp) |
|
175 | visit.append(fp) | |
169 |
|
176 | |||
170 | if scmutil.istreemanifest(repo): |
|
177 | if scmutil.istreemanifest(repo): | |
171 |
for |
|
178 | for entry in repo.store.datafiles(): | |
|
179 | u = entry.unencoded_path | |||
172 | if u.startswith(b'meta/') and ( |
|
180 | if u.startswith(b'meta/') and ( | |
173 | u.endswith(b'.i') or u.endswith(b'.d') |
|
181 | u.endswith(b'.i') or u.endswith(b'.d') | |
174 | ): |
|
182 | ): | |
175 |
yield |
|
183 | yield entry | |
176 |
|
184 | |||
177 | # Return .d and .i files that do not match the shallow pattern |
|
185 | # Return .d and .i files that do not match the shallow pattern | |
178 | match = state.match |
|
186 | match = state.match | |
179 | if match and not match.always(): |
|
187 | if match and not match.always(): | |
180 |
for |
|
188 | for entry in repo.store.datafiles(): | |
|
189 | u = entry.unencoded_path | |||
181 | f = u[5:-2] # trim data/... and .i/.d |
|
190 | f = u[5:-2] # trim data/... and .i/.d | |
182 | if not state.match(f): |
|
191 | if not state.match(f): | |
183 |
yield |
|
192 | yield entry | |
184 |
|
193 | |||
185 | for x in repo.store.topfiles(): |
|
194 | for x in repo.store.topfiles(): | |
186 | if state.noflatmf and x[1][:11] == b'00manifest.': |
|
195 | if state.noflatmf and x[1][:11] == b'00manifest.': |
@@ -444,7 +444,9 b' def manifestrevlogs(repo):' | |||||
444 | if scmutil.istreemanifest(repo): |
|
444 | if scmutil.istreemanifest(repo): | |
445 | # This logic is safe if treemanifest isn't enabled, but also |
|
445 | # This logic is safe if treemanifest isn't enabled, but also | |
446 | # pointless, so we skip it if treemanifest isn't enabled. |
|
446 | # pointless, so we skip it if treemanifest isn't enabled. | |
447 |
for |
|
447 | for entry in repo.store.datafiles(): | |
|
448 | unencoded = entry.unencoded_path | |||
|
449 | # XXX use the entry.revlog_type instead | |||
448 | if unencoded.startswith(b'meta/') and unencoded.endswith( |
|
450 | if unencoded.startswith(b'meta/') and unencoded.endswith( | |
449 | b'00manifest.i' |
|
451 | b'00manifest.i' | |
450 | ): |
|
452 | ): |
@@ -825,9 +825,13 b' def repair_issue6528(' | |||||
825 |
|
825 | |||
826 | with context(): |
|
826 | with context(): | |
827 | files = list( |
|
827 | files = list( | |
828 |
|
|
828 | entry | |
829 |
for |
|
829 | for entry in repo.store.datafiles() | |
830 | if path.endswith(b'.i') and file_type & store.FILEFLAGS_FILELOG |
|
830 | if ( | |
|
831 | entry.unencoded_path.endswith(b'.i') | |||
|
832 | and entry.is_revlog | |||
|
833 | and entry.revlog_type == store.FILEFLAGS_FILELOG | |||
|
834 | ) | |||
831 | ) |
|
835 | ) | |
832 |
|
836 | |||
833 | progress = ui.makeprogress( |
|
837 | progress = ui.makeprogress( | |
@@ -837,7 +841,8 b' def repair_issue6528(' | |||||
837 | ) |
|
841 | ) | |
838 | found_nothing = True |
|
842 | found_nothing = True | |
839 |
|
843 | |||
840 |
for |
|
844 | for entry in files: | |
|
845 | path = entry.unencoded_path | |||
841 | progress.increment() |
|
846 | progress.increment() | |
842 | filename = _get_filename_from_filelog_index(path) |
|
847 | filename = _get_filename_from_filelog_index(path) | |
843 | fl = _filelog_from_filename(repo, filename) |
|
848 | fl = _filelog_from_filename(repo, filename) |
@@ -10,9 +10,11 b' import functools' | |||||
10 | import os |
|
10 | import os | |
11 | import re |
|
11 | import re | |
12 | import stat |
|
12 | import stat | |
|
13 | from typing import Generator | |||
13 |
|
14 | |||
14 | from .i18n import _ |
|
15 | from .i18n import _ | |
15 | from .pycompat import getattr |
|
16 | from .pycompat import getattr | |
|
17 | from .thirdparty import attr | |||
16 | from .node import hex |
|
18 | from .node import hex | |
17 | from . import ( |
|
19 | from . import ( | |
18 | changelog, |
|
20 | changelog, | |
@@ -451,6 +453,20 b' FILETYPE_FILELOG_OTHER = FILEFLAGS_FILEL' | |||||
451 | FILETYPE_OTHER = FILEFLAGS_OTHER |
|
453 | FILETYPE_OTHER = FILEFLAGS_OTHER | |
452 |
|
454 | |||
453 |
|
455 | |||
|
456 | @attr.s(slots=True) | |||
|
457 | class StoreEntry: | |||
|
458 | """An entry in the store | |||
|
459 | ||||
|
460 | This is returned by `store.walk` and represent some data in the store.""" | |||
|
461 | ||||
|
462 | unencoded_path = attr.ib() | |||
|
463 | is_revlog = attr.ib(default=False) | |||
|
464 | revlog_type = attr.ib(default=None) | |||
|
465 | is_revlog_main = attr.ib(default=None) | |||
|
466 | is_volatile = attr.ib(default=False) | |||
|
467 | file_size = attr.ib(default=None) | |||
|
468 | ||||
|
469 | ||||
454 | class basicstore: |
|
470 | class basicstore: | |
455 | '''base class for local repository stores''' |
|
471 | '''base class for local repository stores''' | |
456 |
|
472 | |||
@@ -500,7 +516,9 b' class basicstore:' | |||||
500 | rootstore = manifest.manifestrevlog(repo.nodeconstants, self.vfs) |
|
516 | rootstore = manifest.manifestrevlog(repo.nodeconstants, self.vfs) | |
501 | return manifest.manifestlog(self.vfs, repo, rootstore, storenarrowmatch) |
|
517 | return manifest.manifestlog(self.vfs, repo, rootstore, storenarrowmatch) | |
502 |
|
518 | |||
503 | def datafiles(self, matcher=None, undecodable=None): |
|
519 | def datafiles( | |
|
520 | self, matcher=None, undecodable=None | |||
|
521 | ) -> Generator[StoreEntry, None, None]: | |||
504 | """Like walk, but excluding the changelog and root manifest. |
|
522 | """Like walk, but excluding the changelog and root manifest. | |
505 |
|
523 | |||
506 | When [undecodable] is None, revlogs names that can't be |
|
524 | When [undecodable] is None, revlogs names that can't be | |
@@ -510,20 +528,35 b' class basicstore:' | |||||
510 | files = self._walk(b'data', True) + self._walk(b'meta', True) |
|
528 | files = self._walk(b'data', True) + self._walk(b'meta', True) | |
511 | for (t, u, s) in files: |
|
529 | for (t, u, s) in files: | |
512 | if t is not None: |
|
530 | if t is not None: | |
513 | yield (FILEFLAGS_FILELOG | t, u, s) |
|
531 | yield StoreEntry( | |
|
532 | unencoded_path=u, | |||
|
533 | is_revlog=True, | |||
|
534 | revlog_type=FILEFLAGS_FILELOG, | |||
|
535 | is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN), | |||
|
536 | is_volatile=bool(t & FILEFLAGS_VOLATILE), | |||
|
537 | file_size=s, | |||
|
538 | ) | |||
514 |
|
539 | |||
515 | def topfiles(self): |
|
540 | def topfiles(self) -> Generator[StoreEntry, None, None]: | |
516 | # yield manifest before changelog |
|
541 | # yield manifest before changelog | |
517 | files = reversed(self._walk(b'', False)) |
|
542 | files = reversed(self._walk(b'', False)) | |
518 | for (t, u, s) in files: |
|
543 | for (t, u, s) in files: | |
519 | if u.startswith(b'00changelog'): |
|
544 | if u.startswith(b'00changelog'): | |
520 |
|
|
545 | revlog_type = FILEFLAGS_CHANGELOG | |
521 | elif u.startswith(b'00manifest'): |
|
546 | elif u.startswith(b'00manifest'): | |
522 |
|
|
547 | revlog_type = FILEFLAGS_MANIFESTLOG | |
523 | else: |
|
548 | else: | |
524 | yield (FILETYPE_OTHER | t, u, s) |
|
549 | revlog_type = None | |
|
550 | yield StoreEntry( | |||
|
551 | unencoded_path=u, | |||
|
552 | is_revlog=revlog_type is not None, | |||
|
553 | revlog_type=revlog_type, | |||
|
554 | is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN), | |||
|
555 | is_volatile=bool(t & FILEFLAGS_VOLATILE), | |||
|
556 | file_size=s, | |||
|
557 | ) | |||
525 |
|
558 | |||
526 | def walk(self, matcher=None): |
|
559 | def walk(self, matcher=None) -> Generator[StoreEntry, None, None]: | |
527 | """return files related to data storage (ie: revlogs) |
|
560 | """return files related to data storage (ie: revlogs) | |
528 |
|
561 | |||
529 | yields (file_type, unencoded, size) |
|
562 | yields (file_type, unencoded, size) | |
@@ -576,9 +609,12 b' class encodedstore(basicstore):' | |||||
576 | # However that might change so we should probably add a test and encoding |
|
609 | # However that might change so we should probably add a test and encoding | |
577 | # decoding for it too. see issue6548 |
|
610 | # decoding for it too. see issue6548 | |
578 |
|
611 | |||
579 | def datafiles(self, matcher=None, undecodable=None): |
|
612 | def datafiles( | |
580 | for t, f1, size in super(encodedstore, self).datafiles(): |
|
613 | self, matcher=None, undecodable=None | |
|
614 | ) -> Generator[StoreEntry, None, None]: | |||
|
615 | for entry in super(encodedstore, self).datafiles(): | |||
581 | try: |
|
616 | try: | |
|
617 | f1 = entry.unencoded_path | |||
582 | f2 = decodefilename(f1) |
|
618 | f2 = decodefilename(f1) | |
583 | except KeyError: |
|
619 | except KeyError: | |
584 | if undecodable is None: |
|
620 | if undecodable is None: | |
@@ -589,7 +625,8 b' class encodedstore(basicstore):' | |||||
589 | continue |
|
625 | continue | |
590 | if not _matchtrackedpath(f2, matcher): |
|
626 | if not _matchtrackedpath(f2, matcher): | |
591 | continue |
|
627 | continue | |
592 | yield t, f2, size |
|
628 | entry.unencoded_path = f2 | |
|
629 | yield entry | |||
593 |
|
630 | |||
594 | def join(self, f): |
|
631 | def join(self, f): | |
595 | return self.path + b'/' + encodefilename(f) |
|
632 | return self.path + b'/' + encodefilename(f) | |
@@ -785,7 +822,9 b' class fncachestore(basicstore):' | |||||
785 | def getsize(self, path): |
|
822 | def getsize(self, path): | |
786 | return self.rawvfs.stat(path).st_size |
|
823 | return self.rawvfs.stat(path).st_size | |
787 |
|
824 | |||
788 | def datafiles(self, matcher=None, undecodable=None): |
|
825 | def datafiles( | |
|
826 | self, matcher=None, undecodable=None | |||
|
827 | ) -> Generator[StoreEntry, None, None]: | |||
789 | for f in sorted(self.fncache): |
|
828 | for f in sorted(self.fncache): | |
790 | if not _matchtrackedpath(f, matcher): |
|
829 | if not _matchtrackedpath(f, matcher): | |
791 | continue |
|
830 | continue | |
@@ -799,7 +838,14 b' class fncachestore(basicstore):' | |||||
799 | continue |
|
838 | continue | |
800 | t |= FILEFLAGS_FILELOG |
|
839 | t |= FILEFLAGS_FILELOG | |
801 | try: |
|
840 | try: | |
802 |
yield |
|
841 | yield StoreEntry( | |
|
842 | unencoded_path=f, | |||
|
843 | is_revlog=True, | |||
|
844 | revlog_type=FILEFLAGS_FILELOG, | |||
|
845 | is_revlog_main=bool(t & FILEFLAGS_REVLOG_MAIN), | |||
|
846 | is_volatile=bool(t & FILEFLAGS_VOLATILE), | |||
|
847 | file_size=self.getsize(ef), | |||
|
848 | ) | |||
803 | except FileNotFoundError: |
|
849 | except FileNotFoundError: | |
804 | pass |
|
850 | pass | |
805 |
|
851 |
@@ -269,10 +269,10 b' def generatev1(repo):' | |||||
269 | # Get consistent snapshot of repo, lock during scan. |
|
269 | # Get consistent snapshot of repo, lock during scan. | |
270 | with repo.lock(): |
|
270 | with repo.lock(): | |
271 | repo.ui.debug(b'scanning\n') |
|
271 | repo.ui.debug(b'scanning\n') | |
272 |
for |
|
272 | for entry in _walkstreamfiles(repo): | |
273 | if size: |
|
273 | if entry.file_size: | |
274 |
entries.append(( |
|
274 | entries.append((entry.unencoded_path, entry.file_size)) | |
275 | total_bytes += size |
|
275 | total_bytes += entry.file_size | |
276 | _test_sync_point_walk_1(repo) |
|
276 | _test_sync_point_walk_1(repo) | |
277 | _test_sync_point_walk_2(repo) |
|
277 | _test_sync_point_walk_2(repo) | |
278 |
|
278 | |||
@@ -677,13 +677,15 b' def _v2_walk(repo, includes, excludes, i' | |||||
677 | if includes or excludes: |
|
677 | if includes or excludes: | |
678 | matcher = narrowspec.match(repo.root, includes, excludes) |
|
678 | matcher = narrowspec.match(repo.root, includes, excludes) | |
679 |
|
679 | |||
680 |
for |
|
680 | for entry in _walkstreamfiles(repo, matcher): | |
681 | if size: |
|
681 | if entry.file_size: | |
682 | ft = _fileappend |
|
682 | ft = _fileappend | |
683 | if rl_type & store.FILEFLAGS_VOLATILE: |
|
683 | if entry.is_volatile: | |
684 | ft = _filefull |
|
684 | ft = _filefull | |
685 |
entries.append( |
|
685 | entries.append( | |
686 | totalfilesize += size |
|
686 | (_srcstore, entry.unencoded_path, ft, entry.file_size) | |
|
687 | ) | |||
|
688 | totalfilesize += entry.file_size | |||
687 | for name in _walkstreamfullstorefiles(repo): |
|
689 | for name in _walkstreamfullstorefiles(repo): | |
688 | if repo.svfs.exists(name): |
|
690 | if repo.svfs.exists(name): | |
689 | totalfilesize += repo.svfs.lstat(name).st_size |
|
691 | totalfilesize += repo.svfs.lstat(name).st_size |
@@ -200,9 +200,10 b' def _clonerevlogs(' | |||||
200 |
|
200 | |||
201 | # Perform a pass to collect metadata. This validates we can open all |
|
201 | # Perform a pass to collect metadata. This validates we can open all | |
202 | # source files and allows a unified progress bar to be displayed. |
|
202 | # source files and allows a unified progress bar to be displayed. | |
203 |
for r |
|
203 | for entry in alldatafiles: | |
204 | if not rl_type & store.FILEFLAGS_REVLOG_MAIN: |
|
204 | if not (entry.is_revlog and entry.is_revlog_main): | |
205 | continue |
|
205 | continue | |
|
206 | unencoded = entry.unencoded_path | |||
206 |
|
207 | |||
207 | # the store.walk function will wrongly pickup transaction backup and |
|
208 | # the store.walk function will wrongly pickup transaction backup and | |
208 | # get confused. As a quick fix for 5.9 release, we ignore those. |
|
209 | # get confused. As a quick fix for 5.9 release, we ignore those. | |
@@ -215,7 +216,7 b' def _clonerevlogs(' | |||||
215 | if unencoded in skip_undo: |
|
216 | if unencoded in skip_undo: | |
216 | continue |
|
217 | continue | |
217 |
|
218 | |||
218 | rl = _revlogfrompath(srcrepo, rl_type, unencoded) |
|
219 | rl = _revlogfrompath(srcrepo, entry.revlog_type, unencoded) | |
219 |
|
220 | |||
220 | info = rl.storageinfo( |
|
221 | info = rl.storageinfo( | |
221 | exclusivefiles=True, |
|
222 | exclusivefiles=True, | |
@@ -232,19 +233,19 b' def _clonerevlogs(' | |||||
232 | srcrawsize += rawsize |
|
233 | srcrawsize += rawsize | |
233 |
|
234 | |||
234 | # This is for the separate progress bars. |
|
235 | # This is for the separate progress bars. | |
235 | if rl_type & store.FILEFLAGS_CHANGELOG: |
|
236 | if entry.revlog_type & store.FILEFLAGS_CHANGELOG: | |
236 | changelogs[unencoded] = rl_type |
|
237 | changelogs[unencoded] = entry.revlog_type | |
237 | crevcount += len(rl) |
|
238 | crevcount += len(rl) | |
238 | csrcsize += datasize |
|
239 | csrcsize += datasize | |
239 | crawsize += rawsize |
|
240 | crawsize += rawsize | |
240 | elif rl_type & store.FILEFLAGS_MANIFESTLOG: |
|
241 | elif entry.revlog_type & store.FILEFLAGS_MANIFESTLOG: | |
241 | manifests[unencoded] = rl_type |
|
242 | manifests[unencoded] = entry.revlog_type | |
242 | mcount += 1 |
|
243 | mcount += 1 | |
243 | mrevcount += len(rl) |
|
244 | mrevcount += len(rl) | |
244 | msrcsize += datasize |
|
245 | msrcsize += datasize | |
245 | mrawsize += rawsize |
|
246 | mrawsize += rawsize | |
246 | elif rl_type & store.FILEFLAGS_FILELOG: |
|
247 | elif entry.revlog_type & store.FILEFLAGS_FILELOG: | |
247 | filelogs[unencoded] = rl_type |
|
248 | filelogs[unencoded] = entry.revlog_type | |
248 | fcount += 1 |
|
249 | fcount += 1 | |
249 | frevcount += len(rl) |
|
250 | frevcount += len(rl) | |
250 | fsrcsize += datasize |
|
251 | fsrcsize += datasize |
@@ -407,7 +407,9 b' class verifier:' | |||||
407 | subdirs = set() |
|
407 | subdirs = set() | |
408 | revlogv1 = self.revlogv1 |
|
408 | revlogv1 = self.revlogv1 | |
409 | undecodable = [] |
|
409 | undecodable = [] | |
410 |
for |
|
410 | for entry in repo.store.datafiles(undecodable=undecodable): | |
|
411 | f = entry.unencoded_path | |||
|
412 | size = entry.file_size | |||
411 | if (size > 0 or not revlogv1) and f.startswith(b'meta/'): |
|
413 | if (size > 0 or not revlogv1) and f.startswith(b'meta/'): | |
412 | storefiles.add(_normpath(f)) |
|
414 | storefiles.add(_normpath(f)) | |
413 | subdirs.add(os.path.dirname(f)) |
|
415 | subdirs.add(os.path.dirname(f)) | |
@@ -472,7 +474,9 b' class verifier:' | |||||
472 |
|
474 | |||
473 | storefiles = set() |
|
475 | storefiles = set() | |
474 | undecodable = [] |
|
476 | undecodable = [] | |
475 |
for |
|
477 | for entry in repo.store.datafiles(undecodable=undecodable): | |
|
478 | size = entry.file_size | |||
|
479 | f = entry.unencoded_path | |||
476 | if (size > 0 or not revlogv1) and f.startswith(b'data/'): |
|
480 | if (size > 0 or not revlogv1) and f.startswith(b'data/'): | |
477 | storefiles.add(_normpath(f)) |
|
481 | storefiles.add(_normpath(f)) | |
478 | for f in undecodable: |
|
482 | for f in undecodable: |
General Comments 0
You need to be logged in to leave comments.
Login now