mercurial/changelog.py
changeset 23201 7e97bf6ee2d6
parent 23088 fe5f044b753d
child 23203 3872d563e01a
equal deleted inserted replaced
23200:48a2eefd3d20 23201:7e97bf6ee2d6
   106 
   106 
   107     def write(self, s):
   107     def write(self, s):
   108         self.data.append(str(s))
   108         self.data.append(str(s))
   109         self.offset += len(s)
   109         self.offset += len(s)
   110 
   110 
   111 def delayopener(opener, target, divert, buf):
   111 def _divertopener(opener, target):
   112     def o(name, mode='r'):
   112     """build an opener that writes in 'target.a' instead of 'target'"""
       
   113     def _divert(name, mode='r'):
   113         if name != target:
   114         if name != target:
   114             return opener(name, mode)
   115             return opener(name, mode)
   115         if divert:
   116         return opener(name + ".a", mode)
   116             return opener(name + ".a", mode.replace('a', 'w'))
   117     return _divert
   117         # otherwise, divert to memory
   118 
       
   119 def _delayopener(opener, target, buf):
       
   120     """build an opener that stores chunks in 'buf' instead of 'target'"""
       
   121     def _delay(name, mode='r'):
       
   122         if name != target:
       
   123             return opener(name, mode)
   118         return appender(opener, name, mode, buf)
   124         return appender(opener, name, mode, buf)
   119     return o
   125     return _delay
   120 
   126 
   121 class changelog(revlog.revlog):
   127 class changelog(revlog.revlog):
   122     def __init__(self, opener):
   128     def __init__(self, opener):
   123         revlog.revlog.__init__(self, opener, "00changelog.i")
   129         revlog.revlog.__init__(self, opener, "00changelog.i")
   124         if self._initempty:
   130         if self._initempty:
   125             # changelogs don't benefit from generaldelta
   131             # changelogs don't benefit from generaldelta
   126             self.version &= ~revlog.REVLOGGENERALDELTA
   132             self.version &= ~revlog.REVLOGGENERALDELTA
   127             self._generaldelta = False
   133             self._generaldelta = False
   128         self._realopener = opener
   134         self._realopener = opener
   129         self._delayed = False
   135         self._delayed = False
   130         self._delaybuf = []
   136         self._delaybuf = None
   131         self._divert = False
   137         self._divert = False
   132         self.filteredrevs = frozenset()
   138         self.filteredrevs = frozenset()
   133 
   139 
   134     def tip(self):
   140     def tip(self):
   135         """filtered version of revlog.tip"""
   141         """filtered version of revlog.tip"""
   218             raise error.FilteredIndexError(rev)
   224             raise error.FilteredIndexError(rev)
   219         return super(changelog, self).flags(rev)
   225         return super(changelog, self).flags(rev)
   220 
   226 
   221     def delayupdate(self):
   227     def delayupdate(self):
   222         "delay visibility of index updates to other readers"
   228         "delay visibility of index updates to other readers"
       
   229 
       
   230         if not self._delayed:
       
   231             if len(self) == 0:
       
   232                 self._divert = True
       
   233                 if self._realopener.exists(self.indexfile + '.a'):
       
   234                     self._realopener.unlink(self.indexfile + '.a')
       
   235                 self.opener = _divertopener(self._realopener, self.indexfile)
       
   236             else:
       
   237                 self._delaybuf = []
       
   238                 self.opener = _delayopener(self._realopener, self.indexfile,
       
   239                                            self._delaybuf)
   223         self._delayed = True
   240         self._delayed = True
   224         self._divert = (len(self) == 0)
       
   225         self._delaybuf = []
       
   226         self.opener = delayopener(self._realopener, self.indexfile,
       
   227                                   self._divert, self._delaybuf)
       
   228 
   241 
   229     def finalize(self, tr):
   242     def finalize(self, tr):
   230         "finalize index updates"
   243         "finalize index updates"
   231         self._delayed = False
   244         self._delayed = False
   232         self.opener = self._realopener
   245         self.opener = self._realopener
   233         # move redirected index data back into place
   246         # move redirected index data back into place
   234         if self._divert:
   247         if self._divert:
       
   248             assert not self._delaybuf
   235             tmpname = self.indexfile + ".a"
   249             tmpname = self.indexfile + ".a"
   236             nfile = self.opener.open(tmpname)
   250             nfile = self.opener.open(tmpname)
   237             nfile.close()
   251             nfile.close()
   238             self.opener.rename(tmpname, self.indexfile)
   252             self.opener.rename(tmpname, self.indexfile)
   239         elif self._delaybuf:
   253         elif self._delaybuf:
   240             fp = self.opener(self.indexfile, 'a')
   254             fp = self.opener(self.indexfile, 'a')
   241             fp.write("".join(self._delaybuf))
   255             fp.write("".join(self._delaybuf))
   242             fp.close()
   256             fp.close()
   243             self._delaybuf = []
   257             self._delaybuf = None
       
   258         self._divert = False
   244         # split when we're done
   259         # split when we're done
   245         self.checkinlinesize(tr)
   260         self.checkinlinesize(tr)
   246 
   261 
   247     def readpending(self, file):
   262     def readpending(self, file):
   248         r = revlog.revlog(self.opener, file)
   263         r = revlog.revlog(self.opener, file)
   260             fp2.write(fp1.read())
   275             fp2.write(fp1.read())
   261             # add pending data
   276             # add pending data
   262             fp2.write("".join(self._delaybuf))
   277             fp2.write("".join(self._delaybuf))
   263             fp2.close()
   278             fp2.close()
   264             # switch modes so finalize can simply rename
   279             # switch modes so finalize can simply rename
   265             self._delaybuf = []
   280             self._delaybuf = None
   266             self._divert = True
   281             self._divert = True
       
   282             self.opener = _divertopener(self._realopener, self.indexfile)
   267 
   283 
   268         if self._divert:
   284         if self._divert:
   269             return True
   285             return True
   270 
   286 
   271         return False
   287         return False