Mercurial > hg
comparison mercurial/store.py @ 46895:6085b7f1536d
store: also return some information about the type of file `walk` found
We start returning of 4th information in the `store.walk` return tuple: the type of the file. This will make it easier for caller to determine which kind of file they are looking at. This should especically help with the `upgrade-repo` code that has to do a lot of fragile index's file name comparison.
Differential Revision: https://phab.mercurial-scm.org/D10315
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Tue, 06 Apr 2021 10:38:03 +0200 |
parents | 6afb5ef1e776 |
children | aed6ceaad6d7 |
comparison
equal
deleted
inserted
replaced
46894:fe34c75f62ab | 46895:6085b7f1536d |
---|---|
385 b'phaseroots', | 385 b'phaseroots', |
386 b'obsstore', | 386 b'obsstore', |
387 b'requires', | 387 b'requires', |
388 ] | 388 ] |
389 | 389 |
390 REVLOG_FILES_EXT = (b'.i', b'.d', b'.n', b'.nd') | 390 REVLOG_FILES_MAIN_EXT = (b'.i', b'i.tmpcensored') |
391 | 391 REVLOG_FILES_OTHER_EXT = (b'.d', b'.n', b'.nd', b'd.tmpcensored') |
392 | 392 |
393 def isrevlog(f, kind, st): | 393 |
394 def is_revlog(f, kind, st): | |
394 if kind != stat.S_IFREG: | 395 if kind != stat.S_IFREG: |
395 return False | 396 return None |
396 return f.endswith(REVLOG_FILES_EXT) | 397 return revlog_type(f) |
398 | |
399 | |
400 def revlog_type(f): | |
401 if f.endswith(REVLOG_FILES_MAIN_EXT): | |
402 return FILEFLAGS_REVLOG_MAIN | |
403 elif f.endswith(REVLOG_FILES_OTHER_EXT): | |
404 return FILETYPE_FILELOG_OTHER | |
405 | |
406 | |
407 # the file is part of changelog data | |
408 FILEFLAGS_CHANGELOG = 1 << 13 | |
409 # the file is part of manifest data | |
410 FILEFLAGS_MANIFESTLOG = 1 << 12 | |
411 # the file is part of filelog data | |
412 FILEFLAGS_FILELOG = 1 << 11 | |
413 # file that are not directly part of a revlog | |
414 FILEFLAGS_OTHER = 1 << 10 | |
415 | |
416 # the main entry point for a revlog | |
417 FILEFLAGS_REVLOG_MAIN = 1 << 1 | |
418 # a secondary file for a revlog | |
419 FILEFLAGS_REVLOG_OTHER = 1 << 0 | |
420 | |
421 FILETYPE_CHANGELOG_MAIN = FILEFLAGS_CHANGELOG | FILEFLAGS_REVLOG_MAIN | |
422 FILETYPE_CHANGELOG_OTHER = FILEFLAGS_CHANGELOG | FILEFLAGS_REVLOG_OTHER | |
423 FILETYPE_MANIFESTLOG_MAIN = FILEFLAGS_MANIFESTLOG | FILEFLAGS_REVLOG_MAIN | |
424 FILETYPE_MANIFESTLOG_OTHER = FILEFLAGS_MANIFESTLOG | FILEFLAGS_REVLOG_OTHER | |
425 FILETYPE_FILELOG_MAIN = FILEFLAGS_FILELOG | FILEFLAGS_REVLOG_MAIN | |
426 FILETYPE_FILELOG_OTHER = FILEFLAGS_FILELOG | FILEFLAGS_REVLOG_OTHER | |
427 FILETYPE_OTHER = FILEFLAGS_OTHER | |
397 | 428 |
398 | 429 |
399 class basicstore(object): | 430 class basicstore(object): |
400 '''base class for local repository stores''' | 431 '''base class for local repository stores''' |
401 | 432 |
423 readdir = self.rawvfs.readdir | 454 readdir = self.rawvfs.readdir |
424 while visit: | 455 while visit: |
425 p = visit.pop() | 456 p = visit.pop() |
426 for f, kind, st in readdir(p, stat=True): | 457 for f, kind, st in readdir(p, stat=True): |
427 fp = p + b'/' + f | 458 fp = p + b'/' + f |
428 if isrevlog(f, kind, st): | 459 rl_type = is_revlog(f, kind, st) |
460 if rl_type is not None: | |
429 n = util.pconvert(fp[striplen:]) | 461 n = util.pconvert(fp[striplen:]) |
430 l.append((decodedir(n), n, st.st_size)) | 462 l.append((rl_type, decodedir(n), n, st.st_size)) |
431 elif kind == stat.S_IFDIR and recurse: | 463 elif kind == stat.S_IFDIR and recurse: |
432 visit.append(fp) | 464 visit.append(fp) |
433 l.sort() | 465 l.sort() |
434 return l | 466 return l |
435 | 467 |
443 def manifestlog(self, repo, storenarrowmatch): | 475 def manifestlog(self, repo, storenarrowmatch): |
444 rootstore = manifest.manifestrevlog(repo.nodeconstants, self.vfs) | 476 rootstore = manifest.manifestrevlog(repo.nodeconstants, self.vfs) |
445 return manifest.manifestlog(self.vfs, repo, rootstore, storenarrowmatch) | 477 return manifest.manifestlog(self.vfs, repo, rootstore, storenarrowmatch) |
446 | 478 |
447 def datafiles(self, matcher=None): | 479 def datafiles(self, matcher=None): |
448 return self._walk(b'data', True) + self._walk(b'meta', True) | 480 files = self._walk(b'data', True) + self._walk(b'meta', True) |
481 for (t, u, e, s) in files: | |
482 yield (FILEFLAGS_FILELOG | t, u, e, s) | |
449 | 483 |
450 def topfiles(self): | 484 def topfiles(self): |
451 # yield manifest before changelog | 485 # yield manifest before changelog |
452 return reversed(self._walk(b'', False)) | 486 files = reversed(self._walk(b'', False)) |
487 for (t, u, e, s) in files: | |
488 if u.startswith(b'00changelog'): | |
489 yield (FILEFLAGS_CHANGELOG | t, u, e, s) | |
490 elif u.startswith(b'00manifest'): | |
491 yield (FILEFLAGS_MANIFESTLOG | t, u, e, s) | |
492 else: | |
493 yield (FILETYPE_OTHER | t, u, e, s) | |
453 | 494 |
454 def walk(self, matcher=None): | 495 def walk(self, matcher=None): |
455 """return file related to data storage (ie: revlogs) | 496 """return file related to data storage (ie: revlogs) |
456 | 497 |
457 yields (unencoded, encoded, size) | 498 yields (file_type, unencoded, encoded, size) |
458 | 499 |
459 if a matcher is passed, storage files of only those tracked paths | 500 if a matcher is passed, storage files of only those tracked paths |
460 are passed with matches the matcher | 501 are passed with matches the matcher |
461 """ | 502 """ |
462 # yield data files first | 503 # yield data files first |
498 self.rawvfs = vfs | 539 self.rawvfs = vfs |
499 self.vfs = vfsmod.filtervfs(vfs, encodefilename) | 540 self.vfs = vfsmod.filtervfs(vfs, encodefilename) |
500 self.opener = self.vfs | 541 self.opener = self.vfs |
501 | 542 |
502 def datafiles(self, matcher=None): | 543 def datafiles(self, matcher=None): |
503 for a, b, size in super(encodedstore, self).datafiles(): | 544 for t, a, b, size in super(encodedstore, self).datafiles(): |
504 try: | 545 try: |
505 a = decodefilename(a) | 546 a = decodefilename(a) |
506 except KeyError: | 547 except KeyError: |
507 a = None | 548 a = None |
508 if a is not None and not _matchtrackedpath(a, matcher): | 549 if a is not None and not _matchtrackedpath(a, matcher): |
509 continue | 550 continue |
510 yield a, b, size | 551 yield t, a, b, size |
511 | 552 |
512 def join(self, f): | 553 def join(self, f): |
513 return self.path + b'/' + encodefilename(f) | 554 return self.path + b'/' + encodefilename(f) |
514 | 555 |
515 def copylist(self): | 556 def copylist(self): |
694 for f in sorted(self.fncache): | 735 for f in sorted(self.fncache): |
695 if not _matchtrackedpath(f, matcher): | 736 if not _matchtrackedpath(f, matcher): |
696 continue | 737 continue |
697 ef = self.encode(f) | 738 ef = self.encode(f) |
698 try: | 739 try: |
699 yield f, ef, self.getsize(ef) | 740 t = revlog_type(f) |
741 t |= FILEFLAGS_FILELOG | |
742 yield t, f, ef, self.getsize(ef) | |
700 except OSError as err: | 743 except OSError as err: |
701 if err.errno != errno.ENOENT: | 744 if err.errno != errno.ENOENT: |
702 raise | 745 raise |
703 | 746 |
704 def copylist(self): | 747 def copylist(self): |