mercurial/branchmap.py
changeset 24374 77fd1fb538cd
parent 24373 59cc09240afb
child 24375 fe255b2525d5
equal deleted inserted replaced
24373:59cc09240afb 24374:77fd1fb538cd
    96     if revs:
    96     if revs:
    97         partial.update(repo, revs)
    97         partial.update(repo, revs)
    98         partial.write(repo)
    98         partial.write(repo)
    99 
    99 
   100     if repo._revbranchcache is not None:
   100     if repo._revbranchcache is not None:
   101         repo._revbranchcache.write(repo)
   101         repo._revbranchcache.write()
   102 
   102 
   103     assert partial.validfor(repo), filtername
   103     assert partial.validfor(repo), filtername
   104     repo._branchcaches[repo.filtername] = partial
   104     repo._branchcaches[repo.filtername] = partial
   105 
   105 
   106 class branchcache(dict):
   106 class branchcache(dict):
   237         """
   237         """
   238         starttime = time.time()
   238         starttime = time.time()
   239         cl = repo.changelog
   239         cl = repo.changelog
   240         # collect new branch entries
   240         # collect new branch entries
   241         newbranches = {}
   241         newbranches = {}
   242         urepo = repo.unfiltered()
       
   243         ucl = urepo.changelog
       
   244         getbranchinfo = repo.revbranchcache().branchinfo
   242         getbranchinfo = repo.revbranchcache().branchinfo
   245         for r in revgen:
   243         for r in revgen:
   246             branch, closesbranch = getbranchinfo(ucl, r)
   244             branch, closesbranch = getbranchinfo(r)
   247             newbranches.setdefault(branch, []).append(r)
   245             newbranches.setdefault(branch, []).append(r)
   248             if closesbranch:
   246             if closesbranch:
   249                 self._closednodes.add(cl.node(r))
   247                 self._closednodes.add(cl.node(r))
   250 
   248 
   251         # fetch current topological heads to speed up filtering
   249         # fetch current topological heads to speed up filtering
   329     and will grow with it but be 1/8th of its size.
   327     and will grow with it but be 1/8th of its size.
   330     """
   328     """
   331 
   329 
   332     def __init__(self, repo, readonly=True):
   330     def __init__(self, repo, readonly=True):
   333         assert repo.filtername is None
   331         assert repo.filtername is None
       
   332         self._repo = repo
   334         self._names = [] # branch names in local encoding with static index
   333         self._names = [] # branch names in local encoding with static index
   335         self._rbcrevs = array('c') # structs of type _rbcrecfmt
   334         self._rbcrevs = array('c') # structs of type _rbcrecfmt
   336         self._rbcsnameslen = 0
   335         self._rbcsnameslen = 0
   337         try:
   336         try:
   338             bndata = repo.vfs.read(_rbcnames)
   337             bndata = repo.vfs.read(_rbcnames)
   358         if self._rbcrevslen == 0:
   357         if self._rbcrevslen == 0:
   359             self._names = []
   358             self._names = []
   360         self._rbcnamescount = len(self._names) # number of good names on disk
   359         self._rbcnamescount = len(self._names) # number of good names on disk
   361         self._namesreverse = dict((b, r) for r, b in enumerate(self._names))
   360         self._namesreverse = dict((b, r) for r, b in enumerate(self._names))
   362 
   361 
   363     def branchinfo(self, changelog, rev):
   362     def branchinfo(self, rev):
   364         """Return branch name and close flag for rev, using and updating
   363         """Return branch name and close flag for rev, using and updating
   365         persistent cache."""
   364         persistent cache."""
       
   365         changelog = self._repo.changelog
   366         rbcrevidx = rev * _rbcrecsize
   366         rbcrevidx = rev * _rbcrecsize
   367 
   367 
   368         # if requested rev is missing, add and populate all missing revs
   368         # if requested rev is missing, add and populate all missing revs
   369         if len(self._rbcrevs) < rbcrevidx + _rbcrecsize:
   369         if len(self._rbcrevs) < rbcrevidx + _rbcrecsize:
   370             first = len(self._rbcrevs) // _rbcrecsize
   370             first = len(self._rbcrevs) // _rbcrecsize
   371             self._rbcrevs.extend('\0' * (len(changelog) * _rbcrecsize -
   371             self._rbcrevs.extend('\0' * (len(changelog) * _rbcrecsize -
   372                                          len(self._rbcrevs)))
   372                                          len(self._rbcrevs)))
   373             for r in xrange(first, len(changelog)):
   373             for r in xrange(first, len(changelog)):
   374                 self._branchinfo(changelog, r)
   374                 self._branchinfo(r)
   375 
   375 
   376         # fast path: extract data from cache, use it if node is matching
   376         # fast path: extract data from cache, use it if node is matching
   377         reponode = changelog.node(rev)[:_rbcnodelen]
   377         reponode = changelog.node(rev)[:_rbcnodelen]
   378         cachenode, branchidx = unpack(
   378         cachenode, branchidx = unpack(
   379             _rbcrecfmt, buffer(self._rbcrevs, rbcrevidx, _rbcrecsize))
   379             _rbcrecfmt, buffer(self._rbcrevs, rbcrevidx, _rbcrecsize))
   382             branchidx &= _rbcbranchidxmask
   382             branchidx &= _rbcbranchidxmask
   383         if cachenode == reponode:
   383         if cachenode == reponode:
   384             return self._names[branchidx], close
   384             return self._names[branchidx], close
   385         # fall back to slow path and make sure it will be written to disk
   385         # fall back to slow path and make sure it will be written to disk
   386         self._rbcrevslen = min(self._rbcrevslen, rev)
   386         self._rbcrevslen = min(self._rbcrevslen, rev)
   387         return self._branchinfo(changelog, rev)
   387         return self._branchinfo(rev)
   388 
   388 
   389     def _branchinfo(self, changelog, rev):
   389     def _branchinfo(self, rev):
   390         """Retrieve branch info from changelog and update _rbcrevs"""
   390         """Retrieve branch info from changelog and update _rbcrevs"""
       
   391         changelog = self._repo.changelog
   391         b, close = changelog.branchinfo(rev)
   392         b, close = changelog.branchinfo(rev)
   392         if b in self._namesreverse:
   393         if b in self._namesreverse:
   393             branchidx = self._namesreverse[b]
   394             branchidx = self._namesreverse[b]
   394         else:
   395         else:
   395             branchidx = len(self._names)
   396             branchidx = len(self._names)
   402         rec = array('c')
   403         rec = array('c')
   403         rec.fromstring(pack(_rbcrecfmt, reponode, branchidx))
   404         rec.fromstring(pack(_rbcrecfmt, reponode, branchidx))
   404         self._rbcrevs[rbcrevidx:rbcrevidx + _rbcrecsize] = rec
   405         self._rbcrevs[rbcrevidx:rbcrevidx + _rbcrecsize] = rec
   405         return b, close
   406         return b, close
   406 
   407 
   407     def write(self, repo):
   408     def write(self):
   408         """Save branch cache if it is dirty."""
   409         """Save branch cache if it is dirty."""
       
   410         repo = self._repo
   409         if self._rbcnamescount < len(self._names):
   411         if self._rbcnamescount < len(self._names):
   410             try:
   412             try:
   411                 if self._rbcnamescount != 0:
   413                 if self._rbcnamescount != 0:
   412                     f = repo.vfs.open(_rbcnames, 'ab')
   414                     f = repo.vfs.open(_rbcnames, 'ab')
   413                     if f.tell() == self._rbcsnameslen:
   415                     if f.tell() == self._rbcsnameslen: