mercurial/revlog.py
changeset 4964 ee983d0dbea8
parent 4963 c0df0cce64a4
child 4971 3e6dae278c99
equal deleted inserted replaced
4963:c0df0cce64a4 4964:ee983d0dbea8
   334         self.defversion = REVLOG_DEFAULT_VERSION
   334         self.defversion = REVLOG_DEFAULT_VERSION
   335         if hasattr(opener, "defversion"):
   335         if hasattr(opener, "defversion"):
   336             self.defversion = opener.defversion
   336             self.defversion = opener.defversion
   337             if self.defversion & REVLOGNG:
   337             if self.defversion & REVLOGNG:
   338                 self.defversion |= REVLOGNGINLINEDATA
   338                 self.defversion |= REVLOGNGINLINEDATA
   339         self.load()
   339         self._load()
   340 
   340 
   341     def load(self):
   341     def _load(self):
   342         v = self.defversion
   342         v = self.defversion
   343         try:
   343         try:
   344             f = self.opener(self.indexfile)
   344             f = self.opener(self.indexfile)
   345             i = f.read(4)
   345             i = f.read(4)
   346             f.seek(0)
   346             f.seek(0)
   384         else:
   384         else:
   385             self.indexformat = indexformatng
   385             self.indexformat = indexformatng
   386             shaoffset = ngshaoffset
   386             shaoffset = ngshaoffset
   387 
   387 
   388         if i:
   388         if i:
   389             if (lazyparser.safe_to_use and not self.inlinedata() and
   389             if (lazyparser.safe_to_use and not self._inline() and
   390                 st and st.st_size > 10000):
   390                 st and st.st_size > 10000):
   391                 # big index, let's parse it on demand
   391                 # big index, let's parse it on demand
   392                 parser = lazyparser(f, st.st_size, self.indexformat, shaoffset)
   392                 parser = lazyparser(f, st.st_size, self.indexformat, shaoffset)
   393                 self.index = lazyindex(parser)
   393                 self.index = lazyindex(parser)
   394                 self.nodemap = lazymap(parser)
   394                 self.nodemap = lazymap(parser)
   395             else:
   395             else:
   396                 self.parseindex(f, st)
   396                 self._parseindex(f, st)
   397             if self.version != REVLOGV0:
   397             if self.version != REVLOGV0:
   398                 e = list(self.index[0])
   398                 e = list(self.index[0])
   399                 type = gettype(e[0])
   399                 type = gettype(e[0])
   400                 e[0] = offset_type(0, type)
   400                 e[0] = offset_type(0, type)
   401                 self.index[0] = e
   401                 self.index[0] = e
   402         else:
   402         else:
   403             self.nodemap = {nullid: nullrev}
   403             self.nodemap = {nullid: nullrev}
   404             self.index = []
   404             self.index = []
   405 
   405 
   406 
   406     def _parseindex(self, fp, st):
   407     def parseindex(self, fp, st):
       
   408         s = struct.calcsize(self.indexformat)
   407         s = struct.calcsize(self.indexformat)
   409         self.index = []
   408         self.index = []
   410         self.nodemap =  {nullid: nullrev}
   409         self.nodemap =  {nullid: nullrev}
   411         inline = self.inlinedata()
   410         inline = self._inline()
   412         n = 0
   411         n = 0
   413         leftover = None
   412         leftover = None
   414         while True:
   413         while True:
   415             if st:
   414             if st:
   416                 data = fp.read(65536)
   415                 data = fp.read(65536)
   417             else:
   416             else:
   418                 # hack for httprangereader, it doesn't do partial reads well
   417                 # hack for httprangereader, it doesn't do partial reads well
   419                 data = fp.read()
   418                 data = fp.read()
   420             if not data:
   419             if not data:
   421                 break
   420                 break
   422             if n == 0 and self.inlinedata():
   421             if n == 0 and self._inline():
   423                 # cache the first chunk
   422                 # cache the first chunk
   424                 self.chunkcache = (0, data)
   423                 self.chunkcache = (0, data)
   425             if leftover:
   424             if leftover:
   426                 data = leftover + data
   425                 data = leftover + data
   427                 leftover = None
   426                 leftover = None
   447                         break
   446                         break
   448             if not st:
   447             if not st:
   449                 break
   448                 break
   450 
   449 
   451 
   450 
   452     def loadindex(self, start, end):
   451     def _loadindex(self, start, end):
   453         """load a block of indexes all at once from the lazy parser"""
   452         """load a block of indexes all at once from the lazy parser"""
   454         if isinstance(self.index, lazyindex):
   453         if isinstance(self.index, lazyindex):
   455             self.index.p.loadindex(start, end)
   454             self.index.p.loadindex(start, end)
   456 
   455 
   457     def loadindexmap(self):
   456     def _loadindexmap(self):
   458         """loads both the map and the index from the lazy parser"""
   457         """loads both the map and the index from the lazy parser"""
   459         if isinstance(self.index, lazyindex):
   458         if isinstance(self.index, lazyindex):
   460             p = self.index.p
   459             p = self.index.p
   461             p.loadindex()
   460             p.loadindex()
   462             self.nodemap = p.map
   461             self.nodemap = p.map
   463 
   462 
   464     def loadmap(self):
   463     def _loadmap(self):
   465         """loads the map from the lazy parser"""
   464         """loads the map from the lazy parser"""
   466         if isinstance(self.nodemap, lazymap):
   465         if isinstance(self.nodemap, lazymap):
   467             self.nodemap.p.loadmap()
   466             self.nodemap.p.loadmap()
   468             self.nodemap = self.nodemap.p.map
   467             self.nodemap = self.nodemap.p.map
   469 
   468 
   470     def inlinedata(self): return self.version & REVLOGNGINLINEDATA
   469     def _inline(self): return self.version & REVLOGNGINLINEDATA
       
   470 
   471     def tip(self): return self.node(len(self.index) - 1)
   471     def tip(self): return self.node(len(self.index) - 1)
   472     def count(self): return len(self.index)
   472     def count(self): return len(self.index)
   473     def node(self, rev):
   473     def node(self, rev):
   474         return rev == nullrev and nullid or self.index[rev][-1]
   474         return rev == nullrev and nullid or self.index[rev][-1]
   475     def rev(self, node):
   475     def rev(self, node):
   839         """apply a list of patches to a string"""
   839         """apply a list of patches to a string"""
   840         return mdiff.patches(t, pl)
   840         return mdiff.patches(t, pl)
   841 
   841 
   842     def chunk(self, rev, df=None, cachelen=4096):
   842     def chunk(self, rev, df=None, cachelen=4096):
   843         start, length = self.start(rev), self.length(rev)
   843         start, length = self.start(rev), self.length(rev)
   844         inline = self.inlinedata()
   844         inline = self._inline()
   845         if inline:
   845         if inline:
   846             start += (rev + 1) * struct.calcsize(self.indexformat)
   846             start += (rev + 1) * struct.calcsize(self.indexformat)
   847         end = start + length
   847         end = start + length
   848         def loadcache(df):
   848         def loadcache(df):
   849             cache_length = max(cachelen, length) # 4k
   849             cache_length = max(cachelen, length) # 4k
   897         # look up what we need to read
   897         # look up what we need to read
   898         text = None
   898         text = None
   899         rev = self.rev(node)
   899         rev = self.rev(node)
   900         base = self.base(rev)
   900         base = self.base(rev)
   901 
   901 
   902         if self.inlinedata():
   902         if self._inline():
   903             # we probably have the whole chunk cached
   903             # we probably have the whole chunk cached
   904             df = None
   904             df = None
   905         else:
   905         else:
   906             df = self.opener(self.datafile)
   906             df = self.opener(self.datafile)
   907 
   907 
   908         # do we have useful data cached?
   908         # do we have useful data cached?
   909         if self.cache and self.cache[1] >= base and self.cache[1] < rev:
   909         if self.cache and self.cache[1] >= base and self.cache[1] < rev:
   910             base = self.cache[1]
   910             base = self.cache[1]
   911             text = self.cache[2]
   911             text = self.cache[2]
   912             self.loadindex(base, rev + 1)
   912             self._loadindex(base, rev + 1)
   913         else:
   913         else:
   914             self.loadindex(base, rev + 1)
   914             self._loadindex(base, rev + 1)
   915             text = self.chunk(base, df=df)
   915             text = self.chunk(base, df=df)
   916 
   916 
   917         bins = []
   917         bins = []
   918         for r in xrange(base + 1, rev + 1):
   918         for r in xrange(base + 1, rev + 1):
   919             bins.append(self.chunk(r, df=df))
   919             bins.append(self.chunk(r, df=df))
   927 
   927 
   928         self.cache = (node, rev, text)
   928         self.cache = (node, rev, text)
   929         return text
   929         return text
   930 
   930 
   931     def checkinlinesize(self, tr, fp=None):
   931     def checkinlinesize(self, tr, fp=None):
   932         if not self.inlinedata():
   932         if not self._inline():
   933             return
   933             return
   934         if not fp:
   934         if not fp:
   935             fp = self.opener(self.indexfile, 'r')
   935             fp = self.opener(self.indexfile, 'r')
   936             fp.seek(0, 2)
   936             fp.seek(0, 2)
   937         size = fp.tell()
   937         size = fp.tell()
   984         transaction - the transaction object used for rollback
   984         transaction - the transaction object used for rollback
   985         link - the linkrev data to add
   985         link - the linkrev data to add
   986         p1, p2 - the parent nodeids of the revision
   986         p1, p2 - the parent nodeids of the revision
   987         d - an optional precomputed delta
   987         d - an optional precomputed delta
   988         """
   988         """
   989         if not self.inlinedata():
   989         if not self._inline():
   990             dfh = self.opener(self.datafile, "a")
   990             dfh = self.opener(self.datafile, "a")
   991         else:
   991         else:
   992             dfh = None
   992             dfh = None
   993         ifh = self.opener(self.indexfile, "a+")
   993         ifh = self.opener(self.indexfile, "a+")
   994         return self._addrevision(text, transaction, link, p1, p2, d, ifh, dfh)
   994         return self._addrevision(text, transaction, link, p1, p2, d, ifh, dfh)
  1038 
  1038 
  1039         self.index.append(e)
  1039         self.index.append(e)
  1040         self.nodemap[node] = n
  1040         self.nodemap[node] = n
  1041         entry = struct.pack(self.indexformat, *e)
  1041         entry = struct.pack(self.indexformat, *e)
  1042 
  1042 
  1043         if not self.inlinedata():
  1043         if not self._inline():
  1044             transaction.add(self.datafile, offset)
  1044             transaction.add(self.datafile, offset)
  1045             transaction.add(self.indexfile, n * len(entry))
  1045             transaction.add(self.indexfile, n * len(entry))
  1046             if data[0]:
  1046             if data[0]:
  1047                 dfh.write(data[0])
  1047                 dfh.write(data[0])
  1048             dfh.write(data[1])
  1048             dfh.write(data[1])
  1056             ifh.write(l)
  1056             ifh.write(l)
  1057             entry = entry[4:]
  1057             entry = entry[4:]
  1058 
  1058 
  1059         ifh.write(entry)
  1059         ifh.write(entry)
  1060 
  1060 
  1061         if self.inlinedata():
  1061         if self._inline():
  1062             ifh.write(data[0])
  1062             ifh.write(data[0])
  1063             ifh.write(data[1])
  1063             ifh.write(data[1])
  1064             self.checkinlinesize(transaction, ifh)
  1064             self.checkinlinesize(transaction, ifh)
  1065 
  1065 
  1066         self.cache = (node, n, text)
  1066         self.cache = (node, n, text)
  1133             end = self.end(t)
  1133             end = self.end(t)
  1134 
  1134 
  1135         ifh = self.opener(self.indexfile, "a+")
  1135         ifh = self.opener(self.indexfile, "a+")
  1136         ifh.seek(0, 2)
  1136         ifh.seek(0, 2)
  1137         transaction.add(self.indexfile, ifh.tell(), self.count())
  1137         transaction.add(self.indexfile, ifh.tell(), self.count())
  1138         if self.inlinedata():
  1138         if self._inline():
  1139             dfh = None
  1139             dfh = None
  1140         else:
  1140         else:
  1141             transaction.add(self.datafile, end)
  1141             transaction.add(self.datafile, end)
  1142             dfh = self.opener(self.datafile, "a")
  1142             dfh = self.opener(self.datafile, "a")
  1143 
  1143 
  1182                 ifh.flush()
  1182                 ifh.flush()
  1183                 text = self.revision(chain)
  1183                 text = self.revision(chain)
  1184                 text = self.patches(text, [delta])
  1184                 text = self.patches(text, [delta])
  1185                 chk = self._addrevision(text, transaction, link, p1, p2, None,
  1185                 chk = self._addrevision(text, transaction, link, p1, p2, None,
  1186                                         ifh, dfh)
  1186                                         ifh, dfh)
  1187                 if not dfh and not self.inlinedata():
  1187                 if not dfh and not self._inline():
  1188                     # addrevision switched from inline to conventional
  1188                     # addrevision switched from inline to conventional
  1189                     # reopen the index
  1189                     # reopen the index
  1190                     dfh = self.opener(self.datafile, "a")
  1190                     dfh = self.opener(self.datafile, "a")
  1191                     ifh = self.opener(self.indexfile, "a")
  1191                     ifh = self.opener(self.indexfile, "a")
  1192                 if chk != node:
  1192                 if chk != node:
  1198                 else:
  1198                 else:
  1199                     e = (offset_type(end, 0), len(cdelta), textlen, base,
  1199                     e = (offset_type(end, 0), len(cdelta), textlen, base,
  1200                          link, self.rev(p1), self.rev(p2), node)
  1200                          link, self.rev(p1), self.rev(p2), node)
  1201                 self.index.append(e)
  1201                 self.index.append(e)
  1202                 self.nodemap[node] = r
  1202                 self.nodemap[node] = r
  1203                 if self.inlinedata():
  1203                 if self._inline():
  1204                     ifh.write(struct.pack(self.indexformat, *e))
  1204                     ifh.write(struct.pack(self.indexformat, *e))
  1205                     ifh.write(cdelta)
  1205                     ifh.write(cdelta)
  1206                     self.checkinlinesize(transaction, ifh)
  1206                     self.checkinlinesize(transaction, ifh)
  1207                     if not self.inlinedata():
  1207                     if not self._inline():
  1208                         dfh = self.opener(self.datafile, "a")
  1208                         dfh = self.opener(self.datafile, "a")
  1209                         ifh = self.opener(self.indexfile, "a")
  1209                         ifh = self.opener(self.indexfile, "a")
  1210                 else:
  1210                 else:
  1211                     dfh.write(cdelta)
  1211                     dfh.write(cdelta)
  1212                     ifh.write(struct.pack(self.indexformat, *e))
  1212                     ifh.write(struct.pack(self.indexformat, *e))
  1221     def strip(self, rev, minlink):
  1221     def strip(self, rev, minlink):
  1222         if self.count() == 0 or rev >= self.count():
  1222         if self.count() == 0 or rev >= self.count():
  1223             return
  1223             return
  1224 
  1224 
  1225         if isinstance(self.index, lazyindex):
  1225         if isinstance(self.index, lazyindex):
  1226             self.loadindexmap()
  1226             self._loadindexmap()
  1227 
  1227 
  1228         # When stripping away a revision, we need to make sure it
  1228         # When stripping away a revision, we need to make sure it
  1229         # does not actually belong to an older changeset.
  1229         # does not actually belong to an older changeset.
  1230         # The minlink parameter defines the oldest revision
  1230         # The minlink parameter defines the oldest revision
  1231         # we're allowed to strip away.
  1231         # we're allowed to strip away.
  1234             if rev >= self.count():
  1234             if rev >= self.count():
  1235                 return
  1235                 return
  1236 
  1236 
  1237         # first truncate the files on disk
  1237         # first truncate the files on disk
  1238         end = self.start(rev)
  1238         end = self.start(rev)
  1239         if not self.inlinedata():
  1239         if not self._inline():
  1240             df = self.opener(self.datafile, "a")
  1240             df = self.opener(self.datafile, "a")
  1241             df.truncate(end)
  1241             df.truncate(end)
  1242             end = rev * struct.calcsize(self.indexformat)
  1242             end = rev * struct.calcsize(self.indexformat)
  1243         else:
  1243         else:
  1244             end += rev * struct.calcsize(self.indexformat)
  1244             end += rev * struct.calcsize(self.indexformat)
  1274             f.seek(0, 2)
  1274             f.seek(0, 2)
  1275             actual = f.tell()
  1275             actual = f.tell()
  1276             s = struct.calcsize(self.indexformat)
  1276             s = struct.calcsize(self.indexformat)
  1277             i = actual / s
  1277             i = actual / s
  1278             di = actual - (i * s)
  1278             di = actual - (i * s)
  1279             if self.inlinedata():
  1279             if self._inline():
  1280                 databytes = 0
  1280                 databytes = 0
  1281                 for r in xrange(self.count()):
  1281                 for r in xrange(self.count()):
  1282                     databytes += self.length(r)
  1282                     databytes += self.length(r)
  1283                 dd = 0
  1283                 dd = 0
  1284                 di = actual - self.count() * s - databytes
  1284                 di = actual - self.count() * s - databytes