mercurial/branchmap.py
changeset 18132 db25bf1dc828
parent 18131 f0eeb9b3444a
child 18166 3a2e810dd3d8
equal deleted inserted replaced
18131:f0eeb9b3444a 18132:db25bf1dc828
     7 
     7 
     8 from node import bin, hex, nullid, nullrev
     8 from node import bin, hex, nullid, nullrev
     9 import encoding
     9 import encoding
    10 
    10 
    11 def read(repo):
    11 def read(repo):
    12     partial = branchcache()
       
    13     try:
    12     try:
    14         f = repo.opener("cache/branchheads")
    13         f = repo.opener("cache/branchheads")
    15         lines = f.read().split('\n')
    14         lines = f.read().split('\n')
    16         f.close()
    15         f.close()
    17     except (IOError, OSError):
    16     except (IOError, OSError):
    18         return branchcache()
    17         return branchcache()
    19 
    18 
    20     try:
    19     try:
    21         last, lrev = lines.pop(0).split(" ", 1)
    20         last, lrev = lines.pop(0).split(" ", 1)
    22         last, lrev = bin(last), int(lrev)
    21         last, lrev = bin(last), int(lrev)
    23         if lrev >= len(repo) or repo[lrev].node() != last:
    22         partial = branchcache(tipnode=last, tiprev=lrev)
       
    23         if not partial.validfor(repo):
    24             # invalidate the cache
    24             # invalidate the cache
    25             raise ValueError('invalidating branch cache (tip differs)')
    25             raise ValueError('invalidating branch cache (tip differs)')
    26         for l in lines:
    26         for l in lines:
    27             if not l:
    27             if not l:
    28                 continue
    28                 continue
    30             label = encoding.tolocal(label.strip())
    30             label = encoding.tolocal(label.strip())
    31             if not node in repo:
    31             if not node in repo:
    32                 raise ValueError('invalidating branch cache because node '+
    32                 raise ValueError('invalidating branch cache because node '+
    33                                  '%s does not exist' % node)
    33                                  '%s does not exist' % node)
    34             partial.setdefault(label, []).append(bin(node))
    34             partial.setdefault(label, []).append(bin(node))
    35         partial.tipnode = last
       
    36         partial.tiprev = lrev
       
    37     except KeyboardInterrupt:
    35     except KeyboardInterrupt:
    38         raise
    36         raise
    39     except Exception, inst:
    37     except Exception, inst:
    40         if repo.ui.debugflag:
    38         if repo.ui.debugflag:
    41             repo.ui.warn(str(inst), '\n')
    39             repo.ui.warn(str(inst), '\n')
    45 
    43 
    46 
    44 
    47 def updatecache(repo):
    45 def updatecache(repo):
    48     repo = repo.unfiltered()  # Until we get a smarter cache management
    46     repo = repo.unfiltered()  # Until we get a smarter cache management
    49     cl = repo.changelog
    47     cl = repo.changelog
    50     tip = cl.tip()
       
    51     partial = repo._branchcache
    48     partial = repo._branchcache
    52     if partial is not None and partial.tipnode == tip:
       
    53         return
       
    54 
    49 
    55     if partial is None or partial.tipnode not in cl.nodemap:
    50     if partial is None or not partial.validfor(repo):
    56         partial = read(repo)
    51         partial = read(repo)
    57 
    52 
    58     catip = repo._cacheabletip()
    53     catip = repo._cacheabletip()
    59     # if partial.tiprev == catip: cache is already up to date
    54     # if partial.tiprev == catip: cache is already up to date
    60     # if partial.tiprev >  catip: we have uncachable element in `partial` can't
    55     # if partial.tiprev >  catip: we have uncachable element in `partial` can't
    77 
    72 
    78     def __init__(self, entries=(), tipnode=nullid, tiprev=nullrev):
    73     def __init__(self, entries=(), tipnode=nullid, tiprev=nullrev):
    79         super(branchcache, self).__init__(entries)
    74         super(branchcache, self).__init__(entries)
    80         self.tipnode = tipnode
    75         self.tipnode = tipnode
    81         self.tiprev = tiprev
    76         self.tiprev = tiprev
       
    77 
       
    78     def validfor(self, repo):
       
    79         """Is the cache content valide regarding a repo
       
    80 
       
    81         - False when cached tipnode are unknown or if we detect a strip.
       
    82         - True when cache is up to date or a subset of current repo."""
       
    83         try:
       
    84             return self.tipnode == repo.changelog.node(self.tiprev)
       
    85         except IndexError:
       
    86             return False
       
    87 
    82 
    88 
    83     def write(self, repo):
    89     def write(self, repo):
    84         try:
    90         try:
    85             f = repo.opener("cache/branchheads", "w", atomictemp=True)
    91             f = repo.opener("cache/branchheads", "w", atomictemp=True)
    86             f.write("%s %s\n" % (hex(self.tipnode), self.tiprev))
    92             f.write("%s %s\n" % (hex(self.tipnode), self.tiprev))
   155             nodes = [head for head in self[branch]
   161             nodes = [head for head in self[branch]
   156                      if cl.hasnode(head)]
   162                      if cl.hasnode(head)]
   157             if not nodes:
   163             if not nodes:
   158                 droppednodes.extend(nodes)
   164                 droppednodes.extend(nodes)
   159                 del self[branch]
   165                 del self[branch]
   160         try:
   166         if ((not self.validfor(repo)) or (self.tipnode in droppednodes)):
   161             node = cl.node(self.tiprev)
   167 
   162         except IndexError:
       
   163             node = None
       
   164         if ((self.tipnode != node)
       
   165             or (self.tipnode in droppednodes)):
       
   166             # cache key are not valid anymore
   168             # cache key are not valid anymore
   167             self.tipnode = nullid
   169             self.tipnode = nullid
   168             self.tiprev = nullrev
   170             self.tiprev = nullrev
   169             for heads in self.values():
   171             for heads in self.values():
   170                 tiprev = max(cl.rev(node) for node in heads)
   172                 tiprev = max(cl.rev(node) for node in heads)