##// END OF EJS Templates
store: use a StoreEntry object instead of tuple for store files...
marmoute -
r51364:521fec11 default
parent child Browse files
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 f[1] for f in repo.store.datafiles()
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 t, f, size in repo.store.datafiles():
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 t = store.FILETYPE_OTHER
165 yield store.StoreEntry(
166 yield (t, d, st.st_size)
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 (t, u, s) in repo.store.datafiles():
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 (t, u, s)
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 (t, u, s) in repo.store.datafiles():
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 (t, u, s)
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 t, unencoded, size in repo.store.datafiles():
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 (file_type, path)
828 entry
829 for (file_type, path, _s) in repo.store.datafiles()
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 file_type, path in files:
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 yield (FILEFLAGS_CHANGELOG | t, u, s)
545 revlog_type = FILEFLAGS_CHANGELOG
521 elif u.startswith(b'00manifest'):
546 elif u.startswith(b'00manifest'):
522 yield (FILEFLAGS_MANIFESTLOG | t, u, s)
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 t, f, self.getsize(ef)
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 file_type, name, size in _walkstreamfiles(repo):
272 for entry in _walkstreamfiles(repo):
273 if size:
273 if entry.file_size:
274 entries.append((name, size))
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 rl_type, name, size in _walkstreamfiles(repo, matcher):
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((_srcstore, name, ft, size))
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 rl_type, unencoded, size in alldatafiles:
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 t, f, size in repo.store.datafiles(undecodable=undecodable):
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 t, f, size in repo.store.datafiles(undecodable=undecodable):
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