mercurial/branchmap.py
changeset 51519 ec640dc9cebd
parent 51508 0239ebdd0740
child 51520 fe8347b984f3
equal deleted inserted replaced
51518:c7e81615b5c4 51519:ec640dc9cebd
    98         cl = repo.changelog
    98         cl = repo.changelog
    99         filtername = repo.filtername
    99         filtername = repo.filtername
   100         bcache = self._per_filter.get(filtername)
   100         bcache = self._per_filter.get(filtername)
   101         if bcache is None or not bcache.validfor(repo):
   101         if bcache is None or not bcache.validfor(repo):
   102             # cache object missing or cache object stale? Read from disk
   102             # cache object missing or cache object stale? Read from disk
   103             bcache = branchcache.fromfile(repo)
   103             bcache = branch_cache_from_file(repo)
   104 
   104 
   105         revs = []
   105         revs = []
   106         if bcache is None:
   106         if bcache is None:
   107             # no (fresh) cache available anymore, perhaps we can re-use
   107             # no (fresh) cache available anymore, perhaps we can re-use
   108             # the cache for a subset, then extend that to add info on missing
   108             # the cache for a subset, then extend that to add info on missing
   114                 bcache = self._per_filter[subset.filtername].inherit_for(repo)
   114                 bcache = self._per_filter[subset.filtername].inherit_for(repo)
   115                 extrarevs = subset.changelog.filteredrevs - cl.filteredrevs
   115                 extrarevs = subset.changelog.filteredrevs - cl.filteredrevs
   116                 revs.extend(r for r in extrarevs if r <= bcache.tiprev)
   116                 revs.extend(r for r in extrarevs if r <= bcache.tiprev)
   117             else:
   117             else:
   118                 # nothing to fall back on, start empty.
   118                 # nothing to fall back on, start empty.
   119                 bcache = branchcache(repo)
   119                 bcache = new_branch_cache(repo)
   120 
   120 
   121         revs.extend(cl.revs(start=bcache.tiprev + 1))
   121         revs.extend(cl.revs(start=bcache.tiprev + 1))
   122         if revs:
   122         if revs:
   123             bcache.update(repo, revs)
   123             bcache.update(repo, revs)
   124 
   124 
   145                 if c:
   145                 if c:
   146                     closed.add(h)
   146                     closed.add(h)
   147 
   147 
   148         if rbheads:
   148         if rbheads:
   149             rtiprev = max((int(clrev(node)) for node in rbheads))
   149             rtiprev = max((int(clrev(node)) for node in rbheads))
   150             cache = branchcache(
   150             cache = new_branch_cache(
   151                 repo,
   151                 repo,
   152                 remotebranchmap,
   152                 remotebranchmap,
   153                 repo[rtiprev].node(),
   153                 repo[rtiprev].node(),
   154                 rtiprev,
   154                 rtiprev,
   155                 closednodes=closed,
   155                 closednodes=closed,
   197 class _BaseBranchCache:
   197 class _BaseBranchCache:
   198     """A dict like object that hold branches heads cache.
   198     """A dict like object that hold branches heads cache.
   199 
   199 
   200     This cache is used to avoid costly computations to determine all the
   200     This cache is used to avoid costly computations to determine all the
   201     branch heads of a repo.
   201     branch heads of a repo.
   202 
       
   203     The cache is serialized on disk in the following format:
       
   204 
       
   205     <tip hex node> <tip rev number> [optional filtered repo hex hash]
       
   206     <branch head hex node> <open/closed state> <branch name>
       
   207     <branch head hex node> <open/closed state> <branch name>
       
   208     ...
       
   209 
       
   210     The first line is used to check if the cache is still valid. If the
       
   211     branch cache is for a filtered repo view, an optional third hash is
       
   212     included that hashes the hashes of all filtered and obsolete revisions.
       
   213 
       
   214     The open/closed state is represented by a single letter 'o' or 'c'.
       
   215     This field can be used to avoid changelog reads when determining if a
       
   216     branch head closes a branch or not.
       
   217     """
   202     """
   218 
   203 
   219     def __init__(
   204     def __init__(
   220         self,
   205         self,
   221         repo: "localrepo.localrepository",
   206         repo: "localrepo.localrepository",
   418 STATE_CLEAN = 1
   403 STATE_CLEAN = 1
   419 STATE_INHERITED = 2
   404 STATE_INHERITED = 2
   420 STATE_DIRTY = 3
   405 STATE_DIRTY = 3
   421 
   406 
   422 
   407 
   423 class branchcache(_BaseBranchCache):
   408 class _LocalBranchCache(_BaseBranchCache):
   424     """Branchmap info for a local repo or repoview"""
   409     """base class of branch-map info for a local repo or repoview"""
   425 
   410 
   426     _base_filename = b"branch2"
   411     _base_filename = None
   427 
   412 
   428     def __init__(
   413     def __init__(
   429         self,
   414         self,
   430         repo: "localrepo.localrepository",
   415         repo: "localrepo.localrepository",
   431         entries: Union[
   416         entries: Union[
   558 
   543 
   559     @classmethod
   544     @classmethod
   560     def _filename(cls, repo):
   545     def _filename(cls, repo):
   561         """name of a branchcache file for a given repo or repoview"""
   546         """name of a branchcache file for a given repo or repoview"""
   562         filename = cls._base_filename
   547         filename = cls._base_filename
       
   548         assert filename is not None
   563         if repo.filtername:
   549         if repo.filtername:
   564             filename = b'%s-%s' % (filename, repo.filtername)
   550             filename = b'%s-%s' % (filename, repo.filtername)
   565         return filename
   551         return filename
   566 
   552 
   567     def inherit_for(self, repo):
   553     def inherit_for(self, repo):
   739             #
   725             #
   740             # (The cache warming setup by localrepo will update the file later.)
   726             # (The cache warming setup by localrepo will update the file later.)
   741             self.write(repo)
   727             self.write(repo)
   742 
   728 
   743 
   729 
       
   730 def branch_cache_from_file(repo) -> Optional[_LocalBranchCache]:
       
   731     """Build a branch cache from on-disk data if possible"""
       
   732     return BranchCacheV2.fromfile(repo)
       
   733 
       
   734 
       
   735 def new_branch_cache(repo, *args, **kwargs):
       
   736     """Build a new branch cache from argument"""
       
   737     return BranchCacheV2(repo, *args, **kwargs)
       
   738 
       
   739 
       
   740 class BranchCacheV2(_LocalBranchCache):
       
   741     """a branch cache using version 2 of the format on disk
       
   742 
       
   743     The cache is serialized on disk in the following format:
       
   744 
       
   745     <tip hex node> <tip rev number> [optional filtered repo hex hash]
       
   746     <branch head hex node> <open/closed state> <branch name>
       
   747     <branch head hex node> <open/closed state> <branch name>
       
   748     ...
       
   749 
       
   750     The first line is used to check if the cache is still valid. If the
       
   751     branch cache is for a filtered repo view, an optional third hash is
       
   752     included that hashes the hashes of all filtered and obsolete revisions.
       
   753 
       
   754     The open/closed state is represented by a single letter 'o' or 'c'.
       
   755     This field can be used to avoid changelog reads when determining if a
       
   756     branch head closes a branch or not.
       
   757     """
       
   758 
       
   759     _base_filename = b"branch2"
       
   760 
       
   761 
   744 class remotebranchcache(_BaseBranchCache):
   762 class remotebranchcache(_BaseBranchCache):
   745     """Branchmap info for a remote connection, should not write locally"""
   763     """Branchmap info for a remote connection, should not write locally"""
   746 
   764 
   747     def __init__(
   765     def __init__(
   748         self,
   766         self,