mercurial/revlog.py
changeset 39773 2cd93a8d4bde
parent 39769 ba0e0c6b7b61
child 39774 4a2466b2a434
equal deleted inserted replaced
39772:ae531f5e583c 39773:2cd93a8d4bde
   102 
   102 
   103 # max size of revlog with inline data
   103 # max size of revlog with inline data
   104 _maxinline = 131072
   104 _maxinline = 131072
   105 _chunksize = 1048576
   105 _chunksize = 1048576
   106 
   106 
   107 RevlogError = error.RevlogError
       
   108 LookupError = error.LookupError
   107 LookupError = error.LookupError
   109 AmbiguousPrefixLookupError = error.AmbiguousPrefixLookupError
   108 AmbiguousPrefixLookupError = error.AmbiguousPrefixLookupError
   110 CensoredNodeError = error.CensoredNodeError
   109 CensoredNodeError = error.CensoredNodeError
   111 ProgrammingError = error.ProgrammingError
   110 ProgrammingError = error.ProgrammingError
   112 
   111 
   301 
   300 
   302         return revlogoldindex(index), nodemap, None
   301         return revlogoldindex(index), nodemap, None
   303 
   302 
   304     def packentry(self, entry, node, version, rev):
   303     def packentry(self, entry, node, version, rev):
   305         if gettype(entry[0]):
   304         if gettype(entry[0]):
   306             raise RevlogError(_('index entry flags need revlog version 1'))
   305             raise error.RevlogError(_('index entry flags need revlog '
       
   306                                       'version 1'))
   307         e2 = (getoffset(entry[0]), entry[1], entry[3], entry[4],
   307         e2 = (getoffset(entry[0]), entry[1], entry[3], entry[4],
   308               node(entry[5]), node(entry[6]), entry[7])
   308               node(entry[5]), node(entry[6]), entry[7])
   309         return indexformatv0_pack(*e2)
   309         return indexformatv0_pack(*e2)
   310 
   310 
   311 # index ng:
   311 # index ng:
   454                 self._srmingapsize = opts['sparse-read-min-gap-size']
   454                 self._srmingapsize = opts['sparse-read-min-gap-size']
   455             if opts.get('enableellipsis'):
   455             if opts.get('enableellipsis'):
   456                 self._flagprocessors[REVIDX_ELLIPSIS] = ellipsisprocessor
   456                 self._flagprocessors[REVIDX_ELLIPSIS] = ellipsisprocessor
   457 
   457 
   458         if self._chunkcachesize <= 0:
   458         if self._chunkcachesize <= 0:
   459             raise RevlogError(_('revlog chunk cache size %r is not greater '
   459             raise error.RevlogError(_('revlog chunk cache size %r is not '
   460                                 'than 0') % self._chunkcachesize)
   460                                       'greater than 0') % self._chunkcachesize)
   461         elif self._chunkcachesize & (self._chunkcachesize - 1):
   461         elif self._chunkcachesize & (self._chunkcachesize - 1):
   462             raise RevlogError(_('revlog chunk cache size %r is not a power '
   462             raise error.RevlogError(_('revlog chunk cache size %r is not a '
   463                                 'of 2') % self._chunkcachesize)
   463                                       'power of 2') % self._chunkcachesize)
   464 
   464 
   465         indexdata = ''
   465         indexdata = ''
   466         self._initempty = True
   466         self._initempty = True
   467         try:
   467         try:
   468             with self._indexfp() as f:
   468             with self._indexfp() as f:
   483         self._generaldelta = v & FLAG_GENERALDELTA
   483         self._generaldelta = v & FLAG_GENERALDELTA
   484         flags = v & ~0xFFFF
   484         flags = v & ~0xFFFF
   485         fmt = v & 0xFFFF
   485         fmt = v & 0xFFFF
   486         if fmt == REVLOGV0:
   486         if fmt == REVLOGV0:
   487             if flags:
   487             if flags:
   488                 raise RevlogError(_('unknown flags (%#04x) in version %d '
   488                 raise error.RevlogError(_('unknown flags (%#04x) in version %d '
   489                                     'revlog %s') %
   489                                           'revlog %s') %
   490                                   (flags >> 16, fmt, self.indexfile))
   490                                         (flags >> 16, fmt, self.indexfile))
   491         elif fmt == REVLOGV1:
   491         elif fmt == REVLOGV1:
   492             if flags & ~REVLOGV1_FLAGS:
   492             if flags & ~REVLOGV1_FLAGS:
   493                 raise RevlogError(_('unknown flags (%#04x) in version %d '
   493                 raise error.RevlogError(_('unknown flags (%#04x) in version %d '
   494                                     'revlog %s') %
   494                                           'revlog %s') %
   495                                   (flags >> 16, fmt, self.indexfile))
   495                                         (flags >> 16, fmt, self.indexfile))
   496         elif fmt == REVLOGV2:
   496         elif fmt == REVLOGV2:
   497             if flags & ~REVLOGV2_FLAGS:
   497             if flags & ~REVLOGV2_FLAGS:
   498                 raise RevlogError(_('unknown flags (%#04x) in version %d '
   498                 raise error.RevlogError(_('unknown flags (%#04x) in version %d '
   499                                     'revlog %s') %
   499                                           'revlog %s') %
   500                                   (flags >> 16, fmt, self.indexfile))
   500                                         (flags >> 16, fmt, self.indexfile))
   501         else:
   501         else:
   502             raise RevlogError(_('unknown version (%d) in revlog %s') %
   502             raise error.RevlogError(_('unknown version (%d) in revlog %s') %
   503                               (fmt, self.indexfile))
   503                                     (fmt, self.indexfile))
   504 
   504 
   505         self._storedeltachains = True
   505         self._storedeltachains = True
   506 
   506 
   507         self._io = revlogio()
   507         self._io = revlogio()
   508         if self.version == REVLOGV0:
   508         if self.version == REVLOGV0:
   509             self._io = revlogoldio()
   509             self._io = revlogoldio()
   510         try:
   510         try:
   511             d = self._io.parseindex(indexdata, self._inline)
   511             d = self._io.parseindex(indexdata, self._inline)
   512         except (ValueError, IndexError):
   512         except (ValueError, IndexError):
   513             raise RevlogError(_("index %s is corrupted") % (self.indexfile))
   513             raise error.RevlogError(_("index %s is corrupted") %
       
   514                                     self.indexfile)
   514         self.index, nodemap, self._chunkcache = d
   515         self.index, nodemap, self._chunkcache = d
   515         if nodemap is not None:
   516         if nodemap is not None:
   516             self.nodemap = self._nodecache = nodemap
   517             self.nodemap = self._nodecache = nodemap
   517         if not self._chunkcache:
   518         if not self._chunkcache:
   518             self._chunkclear()
   519             self._chunkclear()
   615     def rev(self, node):
   616     def rev(self, node):
   616         try:
   617         try:
   617             return self._nodecache[node]
   618             return self._nodecache[node]
   618         except TypeError:
   619         except TypeError:
   619             raise
   620             raise
   620         except RevlogError:
   621         except error.RevlogError:
   621             # parsers.c radix tree lookup failed
   622             # parsers.c radix tree lookup failed
   622             if node == wdirid or node in wdirfilenodeids:
   623             if node == wdirid or node in wdirfilenodeids:
   623                 raise error.WdirUnsupported
   624                 raise error.WdirUnsupported
   624             raise LookupError(node, self.indexfile, _('no node'))
   625             raise LookupError(node, self.indexfile, _('no node'))
   625         except KeyError:
   626         except KeyError:
  1266         try:
  1267         try:
  1267             partial = self.index.partialmatch(id)
  1268             partial = self.index.partialmatch(id)
  1268             if partial and self.hasnode(partial):
  1269             if partial and self.hasnode(partial):
  1269                 if maybewdir:
  1270                 if maybewdir:
  1270                     # single 'ff...' match in radix tree, ambiguous with wdir
  1271                     # single 'ff...' match in radix tree, ambiguous with wdir
  1271                     raise RevlogError
  1272                     raise error.RevlogError
  1272                 return partial
  1273                 return partial
  1273             if maybewdir:
  1274             if maybewdir:
  1274                 # no 'ff...' match in radix tree, wdir identified
  1275                 # no 'ff...' match in radix tree, wdir identified
  1275                 raise error.WdirUnsupported
  1276                 raise error.WdirUnsupported
  1276             return None
  1277             return None
  1277         except RevlogError:
  1278         except error.RevlogError:
  1278             # parsers.c radix tree lookup gave multiple matches
  1279             # parsers.c radix tree lookup gave multiple matches
  1279             # fast path: for unfiltered changelog, radix tree is accurate
  1280             # fast path: for unfiltered changelog, radix tree is accurate
  1280             if not getattr(self, 'filteredrevs', None):
  1281             if not getattr(self, 'filteredrevs', None):
  1281                 raise AmbiguousPrefixLookupError(id, self.indexfile,
  1282                 raise AmbiguousPrefixLookupError(id, self.indexfile,
  1282                                                  _('ambiguous identifier'))
  1283                                                  _('ambiguous identifier'))
  1352 
  1353 
  1353         if not getattr(self, 'filteredrevs', None):
  1354         if not getattr(self, 'filteredrevs', None):
  1354             try:
  1355             try:
  1355                 length = max(self.index.shortest(node), minlength)
  1356                 length = max(self.index.shortest(node), minlength)
  1356                 return disambiguate(hexnode, length)
  1357                 return disambiguate(hexnode, length)
  1357             except RevlogError:
  1358             except error.RevlogError:
  1358                 if node != wdirid:
  1359                 if node != wdirid:
  1359                     raise LookupError(node, self.indexfile, _('no node'))
  1360                     raise LookupError(node, self.indexfile, _('no node'))
  1360             except AttributeError:
  1361             except AttributeError:
  1361                 # Fall through to pure code
  1362                 # Fall through to pure code
  1362                 pass
  1363                 pass
  1696             return text, True
  1697             return text, True
  1697         if not operation in ('read', 'write'):
  1698         if not operation in ('read', 'write'):
  1698             raise ProgrammingError(_("invalid '%s' operation ") % (operation))
  1699             raise ProgrammingError(_("invalid '%s' operation ") % (operation))
  1699         # Check all flags are known.
  1700         # Check all flags are known.
  1700         if flags & ~REVIDX_KNOWN_FLAGS:
  1701         if flags & ~REVIDX_KNOWN_FLAGS:
  1701             raise RevlogError(_("incompatible revision flag '%#x'") %
  1702             raise error.RevlogError(_("incompatible revision flag '%#x'") %
  1702                               (flags & ~REVIDX_KNOWN_FLAGS))
  1703                                     (flags & ~REVIDX_KNOWN_FLAGS))
  1703         validatehash = True
  1704         validatehash = True
  1704         # Depending on the operation (read or write), the order might be
  1705         # Depending on the operation (read or write), the order might be
  1705         # reversed due to non-commutative transforms.
  1706         # reversed due to non-commutative transforms.
  1706         orderedflags = REVIDX_FLAGS_ORDER
  1707         orderedflags = REVIDX_FLAGS_ORDER
  1707         if operation == 'write':
  1708         if operation == 'write':
  1713             if flag & flags:
  1714             if flag & flags:
  1714                 vhash = True
  1715                 vhash = True
  1715 
  1716 
  1716                 if flag not in self._flagprocessors:
  1717                 if flag not in self._flagprocessors:
  1717                     message = _("missing processor for flag '%#x'") % (flag)
  1718                     message = _("missing processor for flag '%#x'") % (flag)
  1718                     raise RevlogError(message)
  1719                     raise error.RevlogError(message)
  1719 
  1720 
  1720                 processor = self._flagprocessors[flag]
  1721                 processor = self._flagprocessors[flag]
  1721                 if processor is not None:
  1722                 if processor is not None:
  1722                     readtransform, writetransform, rawtransform = processor
  1723                     readtransform, writetransform, rawtransform = processor
  1723 
  1724 
  1742                 p1, p2 = self.parents(node)
  1743                 p1, p2 = self.parents(node)
  1743             if node != self.hash(text, p1, p2):
  1744             if node != self.hash(text, p1, p2):
  1744                 revornode = rev
  1745                 revornode = rev
  1745                 if revornode is None:
  1746                 if revornode is None:
  1746                     revornode = templatefilters.short(hex(node))
  1747                     revornode = templatefilters.short(hex(node))
  1747                 raise RevlogError(_("integrity check failed on %s:%s")
  1748                 raise error.RevlogError(_("integrity check failed on %s:%s")
  1748                     % (self.indexfile, pycompat.bytestr(revornode)))
  1749                     % (self.indexfile, pycompat.bytestr(revornode)))
  1749         except RevlogError:
  1750         except error.RevlogError:
  1750             if self._censorable and _censoredtext(text):
  1751             if self._censorable and _censoredtext(text):
  1751                 raise error.CensoredNodeError(self.indexfile, node, text)
  1752                 raise error.CensoredNodeError(self.indexfile, node, text)
  1752             raise
  1753             raise
  1753 
  1754 
  1754     def _enforceinlinesize(self, tr, fp=None):
  1755     def _enforceinlinesize(self, tr, fp=None):
  1763             (self.start(tiprev) + self.length(tiprev)) < _maxinline):
  1764             (self.start(tiprev) + self.length(tiprev)) < _maxinline):
  1764             return
  1765             return
  1765 
  1766 
  1766         trinfo = tr.find(self.indexfile)
  1767         trinfo = tr.find(self.indexfile)
  1767         if trinfo is None:
  1768         if trinfo is None:
  1768             raise RevlogError(_("%s not found in the transaction")
  1769             raise error.RevlogError(_("%s not found in the transaction")
  1769                               % self.indexfile)
  1770                                     % self.indexfile)
  1770 
  1771 
  1771         trindex = trinfo[2]
  1772         trindex = trinfo[2]
  1772         if trindex is not None:
  1773         if trindex is not None:
  1773             dataoff = self.start(trindex)
  1774             dataoff = self.start(trindex)
  1774         else:
  1775         else:
  1815         flags - the known flags to set on the revision
  1816         flags - the known flags to set on the revision
  1816         deltacomputer - an optional deltacomputer instance shared between
  1817         deltacomputer - an optional deltacomputer instance shared between
  1817             multiple calls
  1818             multiple calls
  1818         """
  1819         """
  1819         if link == nullrev:
  1820         if link == nullrev:
  1820             raise RevlogError(_("attempted to add linkrev -1 to %s")
  1821             raise error.RevlogError(_("attempted to add linkrev -1 to %s")
  1821                               % self.indexfile)
  1822                                     % self.indexfile)
  1822 
  1823 
  1823         if flags:
  1824         if flags:
  1824             node = node or self.hash(text, p1, p2)
  1825             node = node or self.hash(text, p1, p2)
  1825 
  1826 
  1826         rawtext, validatehash = self._processflags(text, flags, 'write')
  1827         rawtext, validatehash = self._processflags(text, flags, 'write')
  1829         # cachedelta.
  1830         # cachedelta.
  1830         if rawtext != text:
  1831         if rawtext != text:
  1831             cachedelta = None
  1832             cachedelta = None
  1832 
  1833 
  1833         if len(rawtext) > _maxentrysize:
  1834         if len(rawtext) > _maxentrysize:
  1834             raise RevlogError(
  1835             raise error.RevlogError(
  1835                 _("%s: size of %d bytes exceeds maximum revlog storage of 2GiB")
  1836                 _("%s: size of %d bytes exceeds maximum revlog storage of 2GiB")
  1836                 % (self.indexfile, len(rawtext)))
  1837                 % (self.indexfile, len(rawtext)))
  1837 
  1838 
  1838         node = node or self.hash(rawtext, p1, p2)
  1839         node = node or self.hash(rawtext, p1, p2)
  1839         if node in self.nodemap:
  1840         if node in self.nodemap:
  1914 
  1915 
  1915         if t == 'x':
  1916         if t == 'x':
  1916             try:
  1917             try:
  1917                 return _zlibdecompress(data)
  1918                 return _zlibdecompress(data)
  1918             except zlib.error as e:
  1919             except zlib.error as e:
  1919                 raise RevlogError(_('revlog decompress error: %s') %
  1920                 raise error.RevlogError(_('revlog decompress error: %s') %
  1920                                   stringutil.forcebytestr(e))
  1921                                         stringutil.forcebytestr(e))
  1921         # '\0' is more common than 'u' so it goes first.
  1922         # '\0' is more common than 'u' so it goes first.
  1922         elif t == '\0':
  1923         elif t == '\0':
  1923             return data
  1924             return data
  1924         elif t == 'u':
  1925         elif t == 'u':
  1925             return util.buffer(data, 1)
  1926             return util.buffer(data, 1)
  1930             try:
  1931             try:
  1931                 engine = util.compengines.forrevlogheader(t)
  1932                 engine = util.compengines.forrevlogheader(t)
  1932                 compressor = engine.revlogcompressor()
  1933                 compressor = engine.revlogcompressor()
  1933                 self._decompressors[t] = compressor
  1934                 self._decompressors[t] = compressor
  1934             except KeyError:
  1935             except KeyError:
  1935                 raise RevlogError(_('unknown compression type %r') % t)
  1936                 raise error.RevlogError(_('unknown compression type %r') % t)
  1936 
  1937 
  1937         return compressor.decompress(data)
  1938         return compressor.decompress(data)
  1938 
  1939 
  1939     def _addrevision(self, node, rawtext, transaction, link, p1, p2, flags,
  1940     def _addrevision(self, node, rawtext, transaction, link, p1, p2, flags,
  1940                      cachedelta, ifh, dfh, alwayscache=False,
  1941                      cachedelta, ifh, dfh, alwayscache=False,
  1951         invariants:
  1952         invariants:
  1952         - rawtext is optional (can be None); if not set, cachedelta must be set.
  1953         - rawtext is optional (can be None); if not set, cachedelta must be set.
  1953           if both are set, they must correspond to each other.
  1954           if both are set, they must correspond to each other.
  1954         """
  1955         """
  1955         if node == nullid:
  1956         if node == nullid:
  1956             raise RevlogError(_("%s: attempt to add null revision") %
  1957             raise error.RevlogError(_("%s: attempt to add null revision") %
  1957                               (self.indexfile))
  1958                                     self.indexfile)
  1958         if node == wdirid or node in wdirfilenodeids:
  1959         if node == wdirid or node in wdirfilenodeids:
  1959             raise RevlogError(_("%s: attempt to add wdir revision") %
  1960             raise error.RevlogError(_("%s: attempt to add wdir revision") %
  1960                               (self.indexfile))
  1961                                     self.indexfile)
  1961 
  1962 
  1962         if self._inline:
  1963         if self._inline:
  1963             fh = ifh
  1964             fh = ifh
  1964         else:
  1965         else:
  1965             fh = dfh
  1966             fh = dfh