changeset 43077 | 687b865b95ad |
parent 43076 | 2372284d9457 |
child 43089 | c59eb1560c44 |
43076:2372284d9457 | 43077:687b865b95ad |
---|---|
140 return int(q & 0xFFFF) |
140 return int(q & 0xFFFF) |
141 |
141 |
142 |
142 |
143 def offset_type(offset, type): |
143 def offset_type(offset, type): |
144 if (type & ~flagutil.REVIDX_KNOWN_FLAGS) != 0: |
144 if (type & ~flagutil.REVIDX_KNOWN_FLAGS) != 0: |
145 raise ValueError('unknown revlog index flags') |
145 raise ValueError(b'unknown revlog index flags') |
146 return int(int(offset) << 16 | type) |
146 return int(int(offset) << 16 | type) |
147 |
147 |
148 |
148 |
149 @attr.s(slots=True, frozen=True) |
149 @attr.s(slots=True, frozen=True) |
150 class _revisioninfo(object): |
150 class _revisioninfo(object): |
195 # 4 bytes: base rev |
195 # 4 bytes: base rev |
196 # 4 bytes: link rev |
196 # 4 bytes: link rev |
197 # 20 bytes: parent 1 nodeid |
197 # 20 bytes: parent 1 nodeid |
198 # 20 bytes: parent 2 nodeid |
198 # 20 bytes: parent 2 nodeid |
199 # 20 bytes: nodeid |
199 # 20 bytes: nodeid |
200 indexformatv0 = struct.Struct(">4l20s20s20s") |
200 indexformatv0 = struct.Struct(b">4l20s20s20s") |
201 indexformatv0_pack = indexformatv0.pack |
201 indexformatv0_pack = indexformatv0.pack |
202 indexformatv0_unpack = indexformatv0.unpack |
202 indexformatv0_unpack = indexformatv0.unpack |
203 |
203 |
204 |
204 |
205 class revlogoldindex(list): |
205 class revlogoldindex(list): |
241 return revlogoldindex(index), nodemap, None |
241 return revlogoldindex(index), nodemap, None |
242 |
242 |
243 def packentry(self, entry, node, version, rev): |
243 def packentry(self, entry, node, version, rev): |
244 if gettype(entry[0]): |
244 if gettype(entry[0]): |
245 raise error.RevlogError( |
245 raise error.RevlogError( |
246 _('index entry flags need revlog ' 'version 1') |
246 _(b'index entry flags need revlog ' b'version 1') |
247 ) |
247 ) |
248 e2 = ( |
248 e2 = ( |
249 getoffset(entry[0]), |
249 getoffset(entry[0]), |
250 entry[1], |
250 entry[1], |
251 entry[3], |
251 entry[3], |
265 # 4 bytes: base rev |
265 # 4 bytes: base rev |
266 # 4 bytes: link rev |
266 # 4 bytes: link rev |
267 # 4 bytes: parent 1 rev |
267 # 4 bytes: parent 1 rev |
268 # 4 bytes: parent 2 rev |
268 # 4 bytes: parent 2 rev |
269 # 32 bytes: nodeid |
269 # 32 bytes: nodeid |
270 indexformatng = struct.Struct(">Qiiiiii20s12x") |
270 indexformatng = struct.Struct(b">Qiiiiii20s12x") |
271 indexformatng_pack = indexformatng.pack |
271 indexformatng_pack = indexformatng.pack |
272 versionformat = struct.Struct(">I") |
272 versionformat = struct.Struct(b">I") |
273 versionformat_pack = versionformat.pack |
273 versionformat_pack = versionformat.pack |
274 versionformat_unpack = versionformat.unpack |
274 versionformat_unpack = versionformat.unpack |
275 |
275 |
276 # corresponds to uncompressed length of indexformatng (2 gigs, 4-byte |
276 # corresponds to uncompressed length of indexformatng (2 gigs, 4-byte |
277 # signed integer) |
277 # signed integer) |
351 and can be used to implement COW semantics or the like. |
351 and can be used to implement COW semantics or the like. |
352 |
352 |
353 """ |
353 """ |
354 self.upperboundcomp = upperboundcomp |
354 self.upperboundcomp = upperboundcomp |
355 self.indexfile = indexfile |
355 self.indexfile = indexfile |
356 self.datafile = datafile or (indexfile[:-2] + ".d") |
356 self.datafile = datafile or (indexfile[:-2] + b".d") |
357 self.opener = opener |
357 self.opener = opener |
358 # When True, indexfile is opened with checkambig=True at writing, to |
358 # When True, indexfile is opened with checkambig=True at writing, to |
359 # avoid file stat ambiguity. |
359 # avoid file stat ambiguity. |
360 self._checkambig = checkambig |
360 self._checkambig = checkambig |
361 self._mmaplargeindex = mmaplargeindex |
361 self._mmaplargeindex = mmaplargeindex |
363 # 3-tuple of (node, rev, text) for a raw revision. |
363 # 3-tuple of (node, rev, text) for a raw revision. |
364 self._revisioncache = None |
364 self._revisioncache = None |
365 # Maps rev to chain base rev. |
365 # Maps rev to chain base rev. |
366 self._chainbasecache = util.lrucachedict(100) |
366 self._chainbasecache = util.lrucachedict(100) |
367 # 2-tuple of (offset, data) of raw data from the revlog at an offset. |
367 # 2-tuple of (offset, data) of raw data from the revlog at an offset. |
368 self._chunkcache = (0, '') |
368 self._chunkcache = (0, b'') |
369 # How much data to read and cache into the raw revlog data cache. |
369 # How much data to read and cache into the raw revlog data cache. |
370 self._chunkcachesize = 65536 |
370 self._chunkcachesize = 65536 |
371 self._maxchainlen = None |
371 self._maxchainlen = None |
372 self._deltabothparents = True |
372 self._deltabothparents = True |
373 self.index = [] |
373 self.index = [] |
374 # Mapping of partial identifiers to full nodes. |
374 # Mapping of partial identifiers to full nodes. |
375 self._pcache = {} |
375 self._pcache = {} |
376 # Mapping of revision integer to full node. |
376 # Mapping of revision integer to full node. |
377 self._nodecache = {nullid: nullrev} |
377 self._nodecache = {nullid: nullrev} |
378 self._nodepos = None |
378 self._nodepos = None |
379 self._compengine = 'zlib' |
379 self._compengine = b'zlib' |
380 self._compengineopts = {} |
380 self._compengineopts = {} |
381 self._maxdeltachainspan = -1 |
381 self._maxdeltachainspan = -1 |
382 self._withsparseread = False |
382 self._withsparseread = False |
383 self._sparserevlog = False |
383 self._sparserevlog = False |
384 self._srdensitythreshold = 0.50 |
384 self._srdensitythreshold = 0.50 |
395 |
395 |
396 def _loadindex(self): |
396 def _loadindex(self): |
397 mmapindexthreshold = None |
397 mmapindexthreshold = None |
398 opts = self.opener.options |
398 opts = self.opener.options |
399 |
399 |
400 if 'revlogv2' in opts: |
400 if b'revlogv2' in opts: |
401 newversionflags = REVLOGV2 | FLAG_INLINE_DATA |
401 newversionflags = REVLOGV2 | FLAG_INLINE_DATA |
402 elif 'revlogv1' in opts: |
402 elif b'revlogv1' in opts: |
403 newversionflags = REVLOGV1 | FLAG_INLINE_DATA |
403 newversionflags = REVLOGV1 | FLAG_INLINE_DATA |
404 if 'generaldelta' in opts: |
404 if b'generaldelta' in opts: |
405 newversionflags |= FLAG_GENERALDELTA |
405 newversionflags |= FLAG_GENERALDELTA |
406 elif 'revlogv0' in self.opener.options: |
406 elif b'revlogv0' in self.opener.options: |
407 newversionflags = REVLOGV0 |
407 newversionflags = REVLOGV0 |
408 else: |
408 else: |
409 newversionflags = REVLOG_DEFAULT_VERSION |
409 newversionflags = REVLOG_DEFAULT_VERSION |
410 |
410 |
411 if 'chunkcachesize' in opts: |
411 if b'chunkcachesize' in opts: |
412 self._chunkcachesize = opts['chunkcachesize'] |
412 self._chunkcachesize = opts[b'chunkcachesize'] |
413 if 'maxchainlen' in opts: |
413 if b'maxchainlen' in opts: |
414 self._maxchainlen = opts['maxchainlen'] |
414 self._maxchainlen = opts[b'maxchainlen'] |
415 if 'deltabothparents' in opts: |
415 if b'deltabothparents' in opts: |
416 self._deltabothparents = opts['deltabothparents'] |
416 self._deltabothparents = opts[b'deltabothparents'] |
417 self._lazydelta = bool(opts.get('lazydelta', True)) |
417 self._lazydelta = bool(opts.get(b'lazydelta', True)) |
418 self._lazydeltabase = False |
418 self._lazydeltabase = False |
419 if self._lazydelta: |
419 if self._lazydelta: |
420 self._lazydeltabase = bool(opts.get('lazydeltabase', False)) |
420 self._lazydeltabase = bool(opts.get(b'lazydeltabase', False)) |
421 if 'compengine' in opts: |
421 if b'compengine' in opts: |
422 self._compengine = opts['compengine'] |
422 self._compengine = opts[b'compengine'] |
423 if 'zlib.level' in opts: |
423 if b'zlib.level' in opts: |
424 self._compengineopts['zlib.level'] = opts['zlib.level'] |
424 self._compengineopts[b'zlib.level'] = opts[b'zlib.level'] |
425 if 'zstd.level' in opts: |
425 if b'zstd.level' in opts: |
426 self._compengineopts['zstd.level'] = opts['zstd.level'] |
426 self._compengineopts[b'zstd.level'] = opts[b'zstd.level'] |
427 if 'maxdeltachainspan' in opts: |
427 if b'maxdeltachainspan' in opts: |
428 self._maxdeltachainspan = opts['maxdeltachainspan'] |
428 self._maxdeltachainspan = opts[b'maxdeltachainspan'] |
429 if self._mmaplargeindex and 'mmapindexthreshold' in opts: |
429 if self._mmaplargeindex and b'mmapindexthreshold' in opts: |
430 mmapindexthreshold = opts['mmapindexthreshold'] |
430 mmapindexthreshold = opts[b'mmapindexthreshold'] |
431 self.hassidedata = bool(opts.get('side-data', False)) |
431 self.hassidedata = bool(opts.get(b'side-data', False)) |
432 if self.hassidedata: |
432 if self.hassidedata: |
433 self._flagprocessors[REVIDX_SIDEDATA] = sidedatautil.processors |
433 self._flagprocessors[REVIDX_SIDEDATA] = sidedatautil.processors |
434 self._sparserevlog = bool(opts.get('sparse-revlog', False)) |
434 self._sparserevlog = bool(opts.get(b'sparse-revlog', False)) |
435 withsparseread = bool(opts.get('with-sparse-read', False)) |
435 withsparseread = bool(opts.get(b'with-sparse-read', False)) |
436 # sparse-revlog forces sparse-read |
436 # sparse-revlog forces sparse-read |
437 self._withsparseread = self._sparserevlog or withsparseread |
437 self._withsparseread = self._sparserevlog or withsparseread |
438 if 'sparse-read-density-threshold' in opts: |
438 if b'sparse-read-density-threshold' in opts: |
439 self._srdensitythreshold = opts['sparse-read-density-threshold'] |
439 self._srdensitythreshold = opts[b'sparse-read-density-threshold'] |
440 if 'sparse-read-min-gap-size' in opts: |
440 if b'sparse-read-min-gap-size' in opts: |
441 self._srmingapsize = opts['sparse-read-min-gap-size'] |
441 self._srmingapsize = opts[b'sparse-read-min-gap-size'] |
442 if opts.get('enableellipsis'): |
442 if opts.get(b'enableellipsis'): |
443 self._flagprocessors[REVIDX_ELLIPSIS] = ellipsisprocessor |
443 self._flagprocessors[REVIDX_ELLIPSIS] = ellipsisprocessor |
444 |
444 |
445 # revlog v0 doesn't have flag processors |
445 # revlog v0 doesn't have flag processors |
446 for flag, processor in opts.get(b'flagprocessors', {}).iteritems(): |
446 for flag, processor in opts.get(b'flagprocessors', {}).iteritems(): |
447 flagutil.insertflagprocessor(flag, processor, self._flagprocessors) |
447 flagutil.insertflagprocessor(flag, processor, self._flagprocessors) |
448 |
448 |
449 if self._chunkcachesize <= 0: |
449 if self._chunkcachesize <= 0: |
450 raise error.RevlogError( |
450 raise error.RevlogError( |
451 _('revlog chunk cache size %r is not ' 'greater than 0') |
451 _(b'revlog chunk cache size %r is not ' b'greater than 0') |
452 % self._chunkcachesize |
452 % self._chunkcachesize |
453 ) |
453 ) |
454 elif self._chunkcachesize & (self._chunkcachesize - 1): |
454 elif self._chunkcachesize & (self._chunkcachesize - 1): |
455 raise error.RevlogError( |
455 raise error.RevlogError( |
456 _('revlog chunk cache size %r is not a ' 'power of 2') |
456 _(b'revlog chunk cache size %r is not a ' b'power of 2') |
457 % self._chunkcachesize |
457 % self._chunkcachesize |
458 ) |
458 ) |
459 |
459 |
460 indexdata = '' |
460 indexdata = b'' |
461 self._initempty = True |
461 self._initempty = True |
462 try: |
462 try: |
463 with self._indexfp() as f: |
463 with self._indexfp() as f: |
464 if ( |
464 if ( |
465 mmapindexthreshold is not None |
465 mmapindexthreshold is not None |
487 fmt = versionflags & 0xFFFF |
487 fmt = versionflags & 0xFFFF |
488 |
488 |
489 if fmt == REVLOGV0: |
489 if fmt == REVLOGV0: |
490 if flags: |
490 if flags: |
491 raise error.RevlogError( |
491 raise error.RevlogError( |
492 _('unknown flags (%#04x) in version %d ' 'revlog %s') |
492 _(b'unknown flags (%#04x) in version %d ' b'revlog %s') |
493 % (flags >> 16, fmt, self.indexfile) |
493 % (flags >> 16, fmt, self.indexfile) |
494 ) |
494 ) |
495 |
495 |
496 self._inline = False |
496 self._inline = False |
497 self._generaldelta = False |
497 self._generaldelta = False |
498 |
498 |
499 elif fmt == REVLOGV1: |
499 elif fmt == REVLOGV1: |
500 if flags & ~REVLOGV1_FLAGS: |
500 if flags & ~REVLOGV1_FLAGS: |
501 raise error.RevlogError( |
501 raise error.RevlogError( |
502 _('unknown flags (%#04x) in version %d ' 'revlog %s') |
502 _(b'unknown flags (%#04x) in version %d ' b'revlog %s') |
503 % (flags >> 16, fmt, self.indexfile) |
503 % (flags >> 16, fmt, self.indexfile) |
504 ) |
504 ) |
505 |
505 |
506 self._inline = versionflags & FLAG_INLINE_DATA |
506 self._inline = versionflags & FLAG_INLINE_DATA |
507 self._generaldelta = versionflags & FLAG_GENERALDELTA |
507 self._generaldelta = versionflags & FLAG_GENERALDELTA |
508 |
508 |
509 elif fmt == REVLOGV2: |
509 elif fmt == REVLOGV2: |
510 if flags & ~REVLOGV2_FLAGS: |
510 if flags & ~REVLOGV2_FLAGS: |
511 raise error.RevlogError( |
511 raise error.RevlogError( |
512 _('unknown flags (%#04x) in version %d ' 'revlog %s') |
512 _(b'unknown flags (%#04x) in version %d ' b'revlog %s') |
513 % (flags >> 16, fmt, self.indexfile) |
513 % (flags >> 16, fmt, self.indexfile) |
514 ) |
514 ) |
515 |
515 |
516 self._inline = versionflags & FLAG_INLINE_DATA |
516 self._inline = versionflags & FLAG_INLINE_DATA |
517 # generaldelta implied by version 2 revlogs. |
517 # generaldelta implied by version 2 revlogs. |
518 self._generaldelta = True |
518 self._generaldelta = True |
519 |
519 |
520 else: |
520 else: |
521 raise error.RevlogError( |
521 raise error.RevlogError( |
522 _('unknown version (%d) in revlog %s') % (fmt, self.indexfile) |
522 _(b'unknown version (%d) in revlog %s') % (fmt, self.indexfile) |
523 ) |
523 ) |
524 # sparse-revlog can't be on without general-delta (issue6056) |
524 # sparse-revlog can't be on without general-delta (issue6056) |
525 if not self._generaldelta: |
525 if not self._generaldelta: |
526 self._sparserevlog = False |
526 self._sparserevlog = False |
527 |
527 |
531 if self.version == REVLOGV0: |
531 if self.version == REVLOGV0: |
532 self._io = revlogoldio() |
532 self._io = revlogoldio() |
533 try: |
533 try: |
534 d = self._io.parseindex(indexdata, self._inline) |
534 d = self._io.parseindex(indexdata, self._inline) |
535 except (ValueError, IndexError): |
535 except (ValueError, IndexError): |
536 raise error.RevlogError(_("index %s is corrupted") % self.indexfile) |
536 raise error.RevlogError( |
537 _(b"index %s is corrupted") % self.indexfile |
|
538 ) |
|
537 self.index, nodemap, self._chunkcache = d |
539 self.index, nodemap, self._chunkcache = d |
538 if nodemap is not None: |
540 if nodemap is not None: |
539 self.nodemap = self._nodecache = nodemap |
541 self.nodemap = self._nodecache = nodemap |
540 if not self._chunkcache: |
542 if not self._chunkcache: |
541 self._chunkclear() |
543 self._chunkclear() |
547 @util.propertycache |
549 @util.propertycache |
548 def _compressor(self): |
550 def _compressor(self): |
549 engine = util.compengines[self._compengine] |
551 engine = util.compengines[self._compengine] |
550 return engine.revlogcompressor(self._compengineopts) |
552 return engine.revlogcompressor(self._compengineopts) |
551 |
553 |
552 def _indexfp(self, mode='r'): |
554 def _indexfp(self, mode=b'r'): |
553 """file object for the revlog's index file""" |
555 """file object for the revlog's index file""" |
554 args = {r'mode': mode} |
556 args = {r'mode': mode} |
555 if mode != 'r': |
557 if mode != b'r': |
556 args[r'checkambig'] = self._checkambig |
558 args[r'checkambig'] = self._checkambig |
557 if mode == 'w': |
559 if mode == b'w': |
558 args[r'atomictemp'] = True |
560 args[r'atomictemp'] = True |
559 return self.opener(self.indexfile, **args) |
561 return self.opener(self.indexfile, **args) |
560 |
562 |
561 def _datafp(self, mode='r'): |
563 def _datafp(self, mode=b'r'): |
562 """file object for the revlog's data file""" |
564 """file object for the revlog's data file""" |
563 return self.opener(self.datafile, mode=mode) |
565 return self.opener(self.datafile, mode=mode) |
564 |
566 |
565 @contextlib.contextmanager |
567 @contextlib.contextmanager |
566 def _datareadfp(self, existingfp=None): |
568 def _datareadfp(self, existingfp=None): |
633 return True |
635 return True |
634 |
636 |
635 def clearcaches(self): |
637 def clearcaches(self): |
636 self._revisioncache = None |
638 self._revisioncache = None |
637 self._chainbasecache.clear() |
639 self._chainbasecache.clear() |
638 self._chunkcache = (0, '') |
640 self._chunkcache = (0, b'') |
639 self._pcache = {} |
641 self._pcache = {} |
640 |
642 |
641 try: |
643 try: |
642 # If we are using the native C version, you are in a fun case |
644 # If we are using the native C version, you are in a fun case |
643 # where self.index, self.nodemap and self._nodecaches is the same |
645 # where self.index, self.nodemap and self._nodecaches is the same |
654 raise |
656 raise |
655 except error.RevlogError: |
657 except error.RevlogError: |
656 # parsers.c radix tree lookup failed |
658 # parsers.c radix tree lookup failed |
657 if node == wdirid or node in wdirfilenodeids: |
659 if node == wdirid or node in wdirfilenodeids: |
658 raise error.WdirUnsupported |
660 raise error.WdirUnsupported |
659 raise error.LookupError(node, self.indexfile, _('no node')) |
661 raise error.LookupError(node, self.indexfile, _(b'no node')) |
660 except KeyError: |
662 except KeyError: |
661 # pure python cache lookup failed |
663 # pure python cache lookup failed |
662 n = self._nodecache |
664 n = self._nodecache |
663 i = self.index |
665 i = self.index |
664 p = self._nodepos |
666 p = self._nodepos |
672 if v == node: |
674 if v == node: |
673 self._nodepos = r - 1 |
675 self._nodepos = r - 1 |
674 return r |
676 return r |
675 if node == wdirid or node in wdirfilenodeids: |
677 if node == wdirid or node in wdirfilenodeids: |
676 raise error.WdirUnsupported |
678 raise error.WdirUnsupported |
677 raise error.LookupError(node, self.indexfile, _('no node')) |
679 raise error.LookupError(node, self.indexfile, _(b'no node')) |
678 |
680 |
679 # Accessors for index entries. |
681 # Accessors for index entries. |
680 |
682 |
681 # First tuple entry is 8 bytes. First 6 bytes are offset. Last 2 bytes |
683 # First tuple entry is 8 bytes. First 6 bytes are offset. Last 2 bytes |
682 # are flags. |
684 # are flags. |
846 # and we're sure ancestors aren't filtered as well |
848 # and we're sure ancestors aren't filtered as well |
847 |
849 |
848 if rustancestor is not None: |
850 if rustancestor is not None: |
849 lazyancestors = rustancestor.LazyAncestors |
851 lazyancestors = rustancestor.LazyAncestors |
850 arg = self.index |
852 arg = self.index |
851 elif util.safehasattr(parsers, 'rustlazyancestors'): |
853 elif util.safehasattr(parsers, b'rustlazyancestors'): |
852 lazyancestors = ancestor.rustlazyancestors |
854 lazyancestors = ancestor.rustlazyancestors |
853 arg = self.index |
855 arg = self.index |
854 else: |
856 else: |
855 lazyancestors = ancestor.lazyancestors |
857 lazyancestors = ancestor.lazyancestors |
856 arg = self._uncheckedparentrevs |
858 arg = self._uncheckedparentrevs |
1287 except error.LookupError: |
1289 except error.LookupError: |
1288 pass # may be partial hex id |
1290 pass # may be partial hex id |
1289 try: |
1291 try: |
1290 # str(rev) |
1292 # str(rev) |
1291 rev = int(id) |
1293 rev = int(id) |
1292 if "%d" % rev != id: |
1294 if b"%d" % rev != id: |
1293 raise ValueError |
1295 raise ValueError |
1294 if rev < 0: |
1296 if rev < 0: |
1295 rev = len(self) + rev |
1297 rev = len(self) + rev |
1296 if rev < 0 or rev >= len(self): |
1298 if rev < 0 or rev >= len(self): |
1297 raise ValueError |
1299 raise ValueError |
1324 except error.RevlogError: |
1326 except error.RevlogError: |
1325 # parsers.c radix tree lookup gave multiple matches |
1327 # parsers.c radix tree lookup gave multiple matches |
1326 # fast path: for unfiltered changelog, radix tree is accurate |
1328 # fast path: for unfiltered changelog, radix tree is accurate |
1327 if not getattr(self, 'filteredrevs', None): |
1329 if not getattr(self, 'filteredrevs', None): |
1328 raise error.AmbiguousPrefixLookupError( |
1330 raise error.AmbiguousPrefixLookupError( |
1329 id, self.indexfile, _('ambiguous identifier') |
1331 id, self.indexfile, _(b'ambiguous identifier') |
1330 ) |
1332 ) |
1331 # fall through to slow path that filters hidden revisions |
1333 # fall through to slow path that filters hidden revisions |
1332 except (AttributeError, ValueError): |
1334 except (AttributeError, ValueError): |
1333 # we are pure python, or key was too short to search radix tree |
1335 # we are pure python, or key was too short to search radix tree |
1334 pass |
1336 pass |
1350 if len(nl) > 0: |
1352 if len(nl) > 0: |
1351 if len(nl) == 1 and not maybewdir: |
1353 if len(nl) == 1 and not maybewdir: |
1352 self._pcache[id] = nl[0] |
1354 self._pcache[id] = nl[0] |
1353 return nl[0] |
1355 return nl[0] |
1354 raise error.AmbiguousPrefixLookupError( |
1356 raise error.AmbiguousPrefixLookupError( |
1355 id, self.indexfile, _('ambiguous identifier') |
1357 id, self.indexfile, _(b'ambiguous identifier') |
1356 ) |
1358 ) |
1357 if maybewdir: |
1359 if maybewdir: |
1358 raise error.WdirUnsupported |
1360 raise error.WdirUnsupported |
1359 return None |
1361 return None |
1360 except TypeError: |
1362 except TypeError: |
1370 return n |
1372 return n |
1371 n = self._partialmatch(id) |
1373 n = self._partialmatch(id) |
1372 if n: |
1374 if n: |
1373 return n |
1375 return n |
1374 |
1376 |
1375 raise error.LookupError(id, self.indexfile, _('no match found')) |
1377 raise error.LookupError(id, self.indexfile, _(b'no match found')) |
1376 |
1378 |
1377 def shortest(self, node, minlength=1): |
1379 def shortest(self, node, minlength=1): |
1378 """Find the shortest unambiguous prefix that matches node.""" |
1380 """Find the shortest unambiguous prefix that matches node.""" |
1379 |
1381 |
1380 def isvalid(prefix): |
1382 def isvalid(prefix): |
1384 return False |
1386 return False |
1385 except error.WdirUnsupported: |
1387 except error.WdirUnsupported: |
1386 # single 'ff...' match |
1388 # single 'ff...' match |
1387 return True |
1389 return True |
1388 if matchednode is None: |
1390 if matchednode is None: |
1389 raise error.LookupError(node, self.indexfile, _('no node')) |
1391 raise error.LookupError(node, self.indexfile, _(b'no node')) |
1390 return True |
1392 return True |
1391 |
1393 |
1392 def maybewdir(prefix): |
1394 def maybewdir(prefix): |
1393 return all(c == 'f' for c in pycompat.iterbytestr(prefix)) |
1395 return all(c == b'f' for c in pycompat.iterbytestr(prefix)) |
1394 |
1396 |
1395 hexnode = hex(node) |
1397 hexnode = hex(node) |
1396 |
1398 |
1397 def disambiguate(hexnode, minlength): |
1399 def disambiguate(hexnode, minlength): |
1398 """Disambiguate against wdirid.""" |
1400 """Disambiguate against wdirid.""" |
1405 try: |
1407 try: |
1406 length = max(self.index.shortest(node), minlength) |
1408 length = max(self.index.shortest(node), minlength) |
1407 return disambiguate(hexnode, length) |
1409 return disambiguate(hexnode, length) |
1408 except error.RevlogError: |
1410 except error.RevlogError: |
1409 if node != wdirid: |
1411 if node != wdirid: |
1410 raise error.LookupError(node, self.indexfile, _('no node')) |
1412 raise error.LookupError(node, self.indexfile, _(b'no node')) |
1411 except AttributeError: |
1413 except AttributeError: |
1412 # Fall through to pure code |
1414 # Fall through to pure code |
1413 pass |
1415 pass |
1414 |
1416 |
1415 if node == wdirid: |
1417 if node == wdirid: |
1472 if offset != realoffset or reallength != length: |
1474 if offset != realoffset or reallength != length: |
1473 startoffset = offset - realoffset |
1475 startoffset = offset - realoffset |
1474 if len(d) - startoffset < length: |
1476 if len(d) - startoffset < length: |
1475 raise error.RevlogError( |
1477 raise error.RevlogError( |
1476 _( |
1478 _( |
1477 'partial read of revlog %s; expected %d bytes from ' |
1479 b'partial read of revlog %s; expected %d bytes from ' |
1478 'offset %d, got %d' |
1480 b'offset %d, got %d' |
1479 ) |
1481 ) |
1480 % ( |
1482 % ( |
1481 self.indexfile if self._inline else self.datafile, |
1483 self.indexfile if self._inline else self.datafile, |
1482 length, |
1484 length, |
1483 realoffset, |
1485 realoffset, |
1488 return util.buffer(d, startoffset, length) |
1490 return util.buffer(d, startoffset, length) |
1489 |
1491 |
1490 if len(d) < length: |
1492 if len(d) < length: |
1491 raise error.RevlogError( |
1493 raise error.RevlogError( |
1492 _( |
1494 _( |
1493 'partial read of revlog %s; expected %d bytes from offset ' |
1495 b'partial read of revlog %s; expected %d bytes from offset ' |
1494 '%d, got %d' |
1496 b'%d, got %d' |
1495 ) |
1497 ) |
1496 % ( |
1498 % ( |
1497 self.indexfile if self._inline else self.datafile, |
1499 self.indexfile if self._inline else self.datafile, |
1498 length, |
1500 length, |
1499 offset, |
1501 offset, |
1627 |
1629 |
1628 return l |
1630 return l |
1629 |
1631 |
1630 def _chunkclear(self): |
1632 def _chunkclear(self): |
1631 """Clear the raw chunk cache.""" |
1633 """Clear the raw chunk cache.""" |
1632 self._chunkcache = (0, '') |
1634 self._chunkcache = (0, b'') |
1633 |
1635 |
1634 def deltaparent(self, rev): |
1636 def deltaparent(self, rev): |
1635 """return deltaparent of the given revision""" |
1637 """return deltaparent of the given revision""" |
1636 base = self.index[rev][3] |
1638 base = self.index[rev][3] |
1637 if base == rev: |
1639 if base == rev: |
1644 def issnapshot(self, rev): |
1646 def issnapshot(self, rev): |
1645 """tells whether rev is a snapshot |
1647 """tells whether rev is a snapshot |
1646 """ |
1648 """ |
1647 if not self._sparserevlog: |
1649 if not self._sparserevlog: |
1648 return self.deltaparent(rev) == nullrev |
1650 return self.deltaparent(rev) == nullrev |
1649 elif util.safehasattr(self.index, 'issnapshot'): |
1651 elif util.safehasattr(self.index, b'issnapshot'): |
1650 # directly assign the method to cache the testing and access |
1652 # directly assign the method to cache the testing and access |
1651 self.issnapshot = self.index.issnapshot |
1653 self.issnapshot = self.index.issnapshot |
1652 return self.issnapshot(rev) |
1654 return self.issnapshot(rev) |
1653 if rev == nullrev: |
1655 if rev == nullrev: |
1654 return True |
1656 return True |
1665 return self.issnapshot(base) |
1667 return self.issnapshot(base) |
1666 |
1668 |
1667 def snapshotdepth(self, rev): |
1669 def snapshotdepth(self, rev): |
1668 """number of snapshot in the chain before this one""" |
1670 """number of snapshot in the chain before this one""" |
1669 if not self.issnapshot(rev): |
1671 if not self.issnapshot(rev): |
1670 raise error.ProgrammingError('revision %d not a snapshot') |
1672 raise error.ProgrammingError(b'revision %d not a snapshot') |
1671 return len(self._deltachain(rev)[0]) - 1 |
1673 return len(self._deltachain(rev)[0]) - 1 |
1672 |
1674 |
1673 def revdiff(self, rev1, rev2): |
1675 def revdiff(self, rev1, rev2): |
1674 """return or calculate a delta between two revisions |
1676 """return or calculate a delta between two revisions |
1675 |
1677 |
1681 |
1683 |
1682 return mdiff.textdiff(self.rawdata(rev1), self.rawdata(rev2)) |
1684 return mdiff.textdiff(self.rawdata(rev1), self.rawdata(rev2)) |
1683 |
1685 |
1684 def _processflags(self, text, flags, operation, raw=False): |
1686 def _processflags(self, text, flags, operation, raw=False): |
1685 """deprecated entry point to access flag processors""" |
1687 """deprecated entry point to access flag processors""" |
1686 msg = '_processflag(...) use the specialized variant' |
1688 msg = b'_processflag(...) use the specialized variant' |
1687 util.nouideprecwarn(msg, '5.2', stacklevel=2) |
1689 util.nouideprecwarn(msg, b'5.2', stacklevel=2) |
1688 if raw: |
1690 if raw: |
1689 return text, flagutil.processflagsraw(self, text, flags) |
1691 return text, flagutil.processflagsraw(self, text, flags) |
1690 elif operation == 'read': |
1692 elif operation == b'read': |
1691 return flagutil.processflagsread(self, text, flags) |
1693 return flagutil.processflagsread(self, text, flags) |
1692 else: # write operation |
1694 else: # write operation |
1693 return flagutil.processflagswrite(self, text, flags) |
1695 return flagutil.processflagswrite(self, text, flags) |
1694 |
1696 |
1695 def revision(self, nodeorrev, _df=None, raw=False): |
1697 def revision(self, nodeorrev, _df=None, raw=False): |
1701 treated as raw data when applying flag transforms. 'raw' should be set |
1703 treated as raw data when applying flag transforms. 'raw' should be set |
1702 to True when generating changegroups or in debug commands. |
1704 to True when generating changegroups or in debug commands. |
1703 """ |
1705 """ |
1704 if raw: |
1706 if raw: |
1705 msg = ( |
1707 msg = ( |
1706 'revlog.revision(..., raw=True) is deprecated, ' |
1708 b'revlog.revision(..., raw=True) is deprecated, ' |
1707 'use revlog.rawdata(...)' |
1709 b'use revlog.rawdata(...)' |
1708 ) |
1710 ) |
1709 util.nouideprecwarn(msg, '5.2', stacklevel=2) |
1711 util.nouideprecwarn(msg, b'5.2', stacklevel=2) |
1710 return self._revisiondata(nodeorrev, _df, raw=raw)[0] |
1712 return self._revisiondata(nodeorrev, _df, raw=raw)[0] |
1711 |
1713 |
1712 def sidedata(self, nodeorrev, _df=None): |
1714 def sidedata(self, nodeorrev, _df=None): |
1713 """a map of extra data related to the changeset but not part of the hash |
1715 """a map of extra data related to the changeset but not part of the hash |
1714 |
1716 |
1727 node = nodeorrev |
1729 node = nodeorrev |
1728 rev = None |
1730 rev = None |
1729 |
1731 |
1730 # fast path the special `nullid` rev |
1732 # fast path the special `nullid` rev |
1731 if node == nullid: |
1733 if node == nullid: |
1732 return "", {} |
1734 return b"", {} |
1733 |
1735 |
1734 # The text as stored inside the revlog. Might be the revision or might |
1736 # The text as stored inside the revlog. Might be the revision or might |
1735 # need to be processed to retrieve the revision. |
1737 # need to be processed to retrieve the revision. |
1736 rawtext = None |
1738 rawtext = None |
1737 |
1739 |
1757 text = rawtext |
1759 text = rawtext |
1758 else: |
1760 else: |
1759 try: |
1761 try: |
1760 r = flagutil.processflagsread(self, rawtext, flags) |
1762 r = flagutil.processflagsread(self, rawtext, flags) |
1761 except error.SidedataHashError as exc: |
1763 except error.SidedataHashError as exc: |
1762 msg = _("integrity check failed on %s:%s sidedata key %d") |
1764 msg = _(b"integrity check failed on %s:%s sidedata key %d") |
1763 msg %= (self.indexfile, pycompat.bytestr(rev), exc.sidedatakey) |
1765 msg %= (self.indexfile, pycompat.bytestr(rev), exc.sidedatakey) |
1764 raise error.RevlogError(msg) |
1766 raise error.RevlogError(msg) |
1765 text, validatehash, sidedata = r |
1767 text, validatehash, sidedata = r |
1766 if validatehash: |
1768 if validatehash: |
1767 self.checkhash(text, node, rev=rev) |
1769 self.checkhash(text, node, rev=rev) |
1849 |
1851 |
1850 revornode = rev |
1852 revornode = rev |
1851 if revornode is None: |
1853 if revornode is None: |
1852 revornode = templatefilters.short(hex(node)) |
1854 revornode = templatefilters.short(hex(node)) |
1853 raise error.RevlogError( |
1855 raise error.RevlogError( |
1854 _("integrity check failed on %s:%s") |
1856 _(b"integrity check failed on %s:%s") |
1855 % (self.indexfile, pycompat.bytestr(revornode)) |
1857 % (self.indexfile, pycompat.bytestr(revornode)) |
1856 ) |
1858 ) |
1857 except error.RevlogError: |
1859 except error.RevlogError: |
1858 if self._censorable and storageutil.iscensoredtext(text): |
1860 if self._censorable and storageutil.iscensoredtext(text): |
1859 raise error.CensoredNodeError(self.indexfile, node, text) |
1861 raise error.CensoredNodeError(self.indexfile, node, text) |
1874 return |
1876 return |
1875 |
1877 |
1876 trinfo = tr.find(self.indexfile) |
1878 trinfo = tr.find(self.indexfile) |
1877 if trinfo is None: |
1879 if trinfo is None: |
1878 raise error.RevlogError( |
1880 raise error.RevlogError( |
1879 _("%s not found in the transaction") % self.indexfile |
1881 _(b"%s not found in the transaction") % self.indexfile |
1880 ) |
1882 ) |
1881 |
1883 |
1882 trindex = trinfo[2] |
1884 trindex = trinfo[2] |
1883 if trindex is not None: |
1885 if trindex is not None: |
1884 dataoff = self.start(trindex) |
1886 dataoff = self.start(trindex) |
1894 fp.close() |
1896 fp.close() |
1895 # We can't use the cached file handle after close(). So prevent |
1897 # We can't use the cached file handle after close(). So prevent |
1896 # its usage. |
1898 # its usage. |
1897 self._writinghandles = None |
1899 self._writinghandles = None |
1898 |
1900 |
1899 with self._indexfp('r') as ifh, self._datafp('w') as dfh: |
1901 with self._indexfp(b'r') as ifh, self._datafp(b'w') as dfh: |
1900 for r in self: |
1902 for r in self: |
1901 dfh.write(self._getsegmentforrevs(r, r, df=ifh)[1]) |
1903 dfh.write(self._getsegmentforrevs(r, r, df=ifh)[1]) |
1902 |
1904 |
1903 with self._indexfp('w') as fp: |
1905 with self._indexfp(b'w') as fp: |
1904 self.version &= ~FLAG_INLINE_DATA |
1906 self.version &= ~FLAG_INLINE_DATA |
1905 self._inline = False |
1907 self._inline = False |
1906 io = self._io |
1908 io = self._io |
1907 for i in self: |
1909 for i in self: |
1908 e = io.packentry(self.index[i], self.node, self.version, i) |
1910 e = io.packentry(self.index[i], self.node, self.version, i) |
1945 deltacomputer - an optional deltacomputer instance shared between |
1947 deltacomputer - an optional deltacomputer instance shared between |
1946 multiple calls |
1948 multiple calls |
1947 """ |
1949 """ |
1948 if link == nullrev: |
1950 if link == nullrev: |
1949 raise error.RevlogError( |
1951 raise error.RevlogError( |
1950 _("attempted to add linkrev -1 to %s") % self.indexfile |
1952 _(b"attempted to add linkrev -1 to %s") % self.indexfile |
1951 ) |
1953 ) |
1952 |
1954 |
1953 if sidedata is None: |
1955 if sidedata is None: |
1954 sidedata = {} |
1956 sidedata = {} |
1955 flags = flags & ~REVIDX_SIDEDATA |
1957 flags = flags & ~REVIDX_SIDEDATA |
1956 elif not self.hassidedata: |
1958 elif not self.hassidedata: |
1957 raise error.ProgrammingError( |
1959 raise error.ProgrammingError( |
1958 _("trying to add sidedata to a revlog who don't support them") |
1960 _(b"trying to add sidedata to a revlog who don't support them") |
1959 ) |
1961 ) |
1960 else: |
1962 else: |
1961 flags |= REVIDX_SIDEDATA |
1963 flags |= REVIDX_SIDEDATA |
1962 |
1964 |
1963 if flags: |
1965 if flags: |
1972 if rawtext != text: |
1974 if rawtext != text: |
1973 cachedelta = None |
1975 cachedelta = None |
1974 |
1976 |
1975 if len(rawtext) > _maxentrysize: |
1977 if len(rawtext) > _maxentrysize: |
1976 raise error.RevlogError( |
1978 raise error.RevlogError( |
1977 _("%s: size of %d bytes exceeds maximum revlog storage of 2GiB") |
1979 _( |
1980 b"%s: size of %d bytes exceeds maximum revlog storage of 2GiB" |
|
1981 ) |
|
1978 % (self.indexfile, len(rawtext)) |
1982 % (self.indexfile, len(rawtext)) |
1979 ) |
1983 ) |
1980 |
1984 |
1981 node = node or self.hash(rawtext, p1, p2) |
1985 node = node or self.hash(rawtext, p1, p2) |
1982 if node in self.nodemap: |
1986 if node in self.nodemap: |
2013 useful when reusing a revision not stored in this revlog (ex: received |
2017 useful when reusing a revision not stored in this revlog (ex: received |
2014 over wire, or read from an external bundle). |
2018 over wire, or read from an external bundle). |
2015 """ |
2019 """ |
2016 dfh = None |
2020 dfh = None |
2017 if not self._inline: |
2021 if not self._inline: |
2018 dfh = self._datafp("a+") |
2022 dfh = self._datafp(b"a+") |
2019 ifh = self._indexfp("a+") |
2023 ifh = self._indexfp(b"a+") |
2020 try: |
2024 try: |
2021 return self._addrevision( |
2025 return self._addrevision( |
2022 node, |
2026 node, |
2023 rawtext, |
2027 rawtext, |
2024 transaction, |
2028 transaction, |
2037 ifh.close() |
2041 ifh.close() |
2038 |
2042 |
2039 def compress(self, data): |
2043 def compress(self, data): |
2040 """Generate a possibly-compressed representation of data.""" |
2044 """Generate a possibly-compressed representation of data.""" |
2041 if not data: |
2045 if not data: |
2042 return '', data |
2046 return b'', data |
2043 |
2047 |
2044 compressed = self._compressor.compress(data) |
2048 compressed = self._compressor.compress(data) |
2045 |
2049 |
2046 if compressed: |
2050 if compressed: |
2047 # The revlog compressor added the header in the returned data. |
2051 # The revlog compressor added the header in the returned data. |
2048 return '', compressed |
2052 return b'', compressed |
2049 |
2053 |
2050 if data[0:1] == '\0': |
2054 if data[0:1] == b'\0': |
2051 return '', data |
2055 return b'', data |
2052 return 'u', data |
2056 return b'u', data |
2053 |
2057 |
2054 def decompress(self, data): |
2058 def decompress(self, data): |
2055 """Decompress a revlog chunk. |
2059 """Decompress a revlog chunk. |
2056 |
2060 |
2057 The chunk is expected to begin with a header identifying the |
2061 The chunk is expected to begin with a header identifying the |
2081 # |
2085 # |
2082 # According to `hg perfrevlogchunks`, this is ~0.5% faster for zlib |
2086 # According to `hg perfrevlogchunks`, this is ~0.5% faster for zlib |
2083 # compressed chunks. And this matters for changelog and manifest reads. |
2087 # compressed chunks. And this matters for changelog and manifest reads. |
2084 t = data[0:1] |
2088 t = data[0:1] |
2085 |
2089 |
2086 if t == 'x': |
2090 if t == b'x': |
2087 try: |
2091 try: |
2088 return _zlibdecompress(data) |
2092 return _zlibdecompress(data) |
2089 except zlib.error as e: |
2093 except zlib.error as e: |
2090 raise error.RevlogError( |
2094 raise error.RevlogError( |
2091 _('revlog decompress error: %s') |
2095 _(b'revlog decompress error: %s') |
2092 % stringutil.forcebytestr(e) |
2096 % stringutil.forcebytestr(e) |
2093 ) |
2097 ) |
2094 # '\0' is more common than 'u' so it goes first. |
2098 # '\0' is more common than 'u' so it goes first. |
2095 elif t == '\0': |
2099 elif t == b'\0': |
2096 return data |
2100 return data |
2097 elif t == 'u': |
2101 elif t == b'u': |
2098 return util.buffer(data, 1) |
2102 return util.buffer(data, 1) |
2099 |
2103 |
2100 try: |
2104 try: |
2101 compressor = self._decompressors[t] |
2105 compressor = self._decompressors[t] |
2102 except KeyError: |
2106 except KeyError: |
2103 try: |
2107 try: |
2104 engine = util.compengines.forrevlogheader(t) |
2108 engine = util.compengines.forrevlogheader(t) |
2105 compressor = engine.revlogcompressor(self._compengineopts) |
2109 compressor = engine.revlogcompressor(self._compengineopts) |
2106 self._decompressors[t] = compressor |
2110 self._decompressors[t] = compressor |
2107 except KeyError: |
2111 except KeyError: |
2108 raise error.RevlogError(_('unknown compression type %r') % t) |
2112 raise error.RevlogError(_(b'unknown compression type %r') % t) |
2109 |
2113 |
2110 return compressor.decompress(data) |
2114 return compressor.decompress(data) |
2111 |
2115 |
2112 def _addrevision( |
2116 def _addrevision( |
2113 self, |
2117 self, |
2137 - rawtext is optional (can be None); if not set, cachedelta must be set. |
2141 - rawtext is optional (can be None); if not set, cachedelta must be set. |
2138 if both are set, they must correspond to each other. |
2142 if both are set, they must correspond to each other. |
2139 """ |
2143 """ |
2140 if node == nullid: |
2144 if node == nullid: |
2141 raise error.RevlogError( |
2145 raise error.RevlogError( |
2142 _("%s: attempt to add null revision") % self.indexfile |
2146 _(b"%s: attempt to add null revision") % self.indexfile |
2143 ) |
2147 ) |
2144 if node == wdirid or node in wdirfilenodeids: |
2148 if node == wdirid or node in wdirfilenodeids: |
2145 raise error.RevlogError( |
2149 raise error.RevlogError( |
2146 _("%s: attempt to add wdir revision") % self.indexfile |
2150 _(b"%s: attempt to add wdir revision") % self.indexfile |
2147 ) |
2151 ) |
2148 |
2152 |
2149 if self._inline: |
2153 if self._inline: |
2150 fh = ifh |
2154 fh = ifh |
2151 else: |
2155 else: |
2254 If ``addrevisioncb`` is defined, it will be called with arguments of |
2258 If ``addrevisioncb`` is defined, it will be called with arguments of |
2255 this revlog and the node that was added. |
2259 this revlog and the node that was added. |
2256 """ |
2260 """ |
2257 |
2261 |
2258 if self._writinghandles: |
2262 if self._writinghandles: |
2259 raise error.ProgrammingError('cannot nest addgroup() calls') |
2263 raise error.ProgrammingError(b'cannot nest addgroup() calls') |
2260 |
2264 |
2261 nodes = [] |
2265 nodes = [] |
2262 |
2266 |
2263 r = len(self) |
2267 r = len(self) |
2264 end = 0 |
2268 end = 0 |
2265 if r: |
2269 if r: |
2266 end = self.end(r - 1) |
2270 end = self.end(r - 1) |
2267 ifh = self._indexfp("a+") |
2271 ifh = self._indexfp(b"a+") |
2268 isize = r * self._io.size |
2272 isize = r * self._io.size |
2269 if self._inline: |
2273 if self._inline: |
2270 transaction.add(self.indexfile, end + isize, r) |
2274 transaction.add(self.indexfile, end + isize, r) |
2271 dfh = None |
2275 dfh = None |
2272 else: |
2276 else: |
2273 transaction.add(self.indexfile, isize, r) |
2277 transaction.add(self.indexfile, isize, r) |
2274 transaction.add(self.datafile, end) |
2278 transaction.add(self.datafile, end) |
2275 dfh = self._datafp("a+") |
2279 dfh = self._datafp(b"a+") |
2276 |
2280 |
2277 def flush(): |
2281 def flush(): |
2278 if dfh: |
2282 if dfh: |
2279 dfh.flush() |
2283 dfh.flush() |
2280 ifh.flush() |
2284 ifh.flush() |
2297 continue |
2301 continue |
2298 |
2302 |
2299 for p in (p1, p2): |
2303 for p in (p1, p2): |
2300 if p not in self.nodemap: |
2304 if p not in self.nodemap: |
2301 raise error.LookupError( |
2305 raise error.LookupError( |
2302 p, self.indexfile, _('unknown parent') |
2306 p, self.indexfile, _(b'unknown parent') |
2303 ) |
2307 ) |
2304 |
2308 |
2305 if deltabase not in self.nodemap: |
2309 if deltabase not in self.nodemap: |
2306 raise error.LookupError( |
2310 raise error.LookupError( |
2307 deltabase, self.indexfile, _('unknown delta base') |
2311 deltabase, self.indexfile, _(b'unknown delta base') |
2308 ) |
2312 ) |
2309 |
2313 |
2310 baserev = self.rev(deltabase) |
2314 baserev = self.rev(deltabase) |
2311 |
2315 |
2312 if baserev != nullrev and self.iscensored(baserev): |
2316 if baserev != nullrev and self.iscensored(baserev): |
2313 # if base is censored, delta must be full replacement in a |
2317 # if base is censored, delta must be full replacement in a |
2314 # single patch operation |
2318 # single patch operation |
2315 hlen = struct.calcsize(">lll") |
2319 hlen = struct.calcsize(b">lll") |
2316 oldlen = self.rawsize(baserev) |
2320 oldlen = self.rawsize(baserev) |
2317 newlen = len(delta) - hlen |
2321 newlen = len(delta) - hlen |
2318 if delta[:hlen] != mdiff.replacediffheader(oldlen, newlen): |
2322 if delta[:hlen] != mdiff.replacediffheader(oldlen, newlen): |
2319 raise error.CensoredBaseError( |
2323 raise error.CensoredBaseError( |
2320 self.indexfile, self.node(baserev) |
2324 self.indexfile, self.node(baserev) |
2350 |
2354 |
2351 if not dfh and not self._inline: |
2355 if not dfh and not self._inline: |
2352 # addrevision switched from inline to conventional |
2356 # addrevision switched from inline to conventional |
2353 # reopen the index |
2357 # reopen the index |
2354 ifh.close() |
2358 ifh.close() |
2355 dfh = self._datafp("a+") |
2359 dfh = self._datafp(b"a+") |
2356 ifh = self._indexfp("a+") |
2360 ifh = self._indexfp(b"a+") |
2357 self._writinghandles = (ifh, dfh) |
2361 self._writinghandles = (ifh, dfh) |
2358 finally: |
2362 finally: |
2359 self._writinghandles = None |
2363 self._writinghandles = None |
2360 |
2364 |
2361 if dfh: |
2365 if dfh: |
2489 nodesorder=None, |
2493 nodesorder=None, |
2490 revisiondata=False, |
2494 revisiondata=False, |
2491 assumehaveparentrevisions=False, |
2495 assumehaveparentrevisions=False, |
2492 deltamode=repository.CG_DELTAMODE_STD, |
2496 deltamode=repository.CG_DELTAMODE_STD, |
2493 ): |
2497 ): |
2494 if nodesorder not in ('nodes', 'storage', 'linear', None): |
2498 if nodesorder not in (b'nodes', b'storage', b'linear', None): |
2495 raise error.ProgrammingError( |
2499 raise error.ProgrammingError( |
2496 'unhandled value for nodesorder: %s' % nodesorder |
2500 b'unhandled value for nodesorder: %s' % nodesorder |
2497 ) |
2501 ) |
2498 |
2502 |
2499 if nodesorder is None and not self._generaldelta: |
2503 if nodesorder is None and not self._generaldelta: |
2500 nodesorder = 'storage' |
2504 nodesorder = b'storage' |
2501 |
2505 |
2502 if ( |
2506 if ( |
2503 not self._storedeltachains |
2507 not self._storedeltachains |
2504 and deltamode != repository.CG_DELTAMODE_PREV |
2508 and deltamode != repository.CG_DELTAMODE_PREV |
2505 ): |
2509 ): |
2518 deltamode=deltamode, |
2522 deltamode=deltamode, |
2519 revisiondata=revisiondata, |
2523 revisiondata=revisiondata, |
2520 assumehaveparentrevisions=assumehaveparentrevisions, |
2524 assumehaveparentrevisions=assumehaveparentrevisions, |
2521 ) |
2525 ) |
2522 |
2526 |
2523 DELTAREUSEALWAYS = 'always' |
2527 DELTAREUSEALWAYS = b'always' |
2524 DELTAREUSESAMEREVS = 'samerevs' |
2528 DELTAREUSESAMEREVS = b'samerevs' |
2525 DELTAREUSENEVER = 'never' |
2529 DELTAREUSENEVER = b'never' |
2526 |
2530 |
2527 DELTAREUSEFULLADD = 'fulladd' |
2531 DELTAREUSEFULLADD = b'fulladd' |
2528 |
2532 |
2529 DELTAREUSEALL = {'always', 'samerevs', 'never', 'fulladd'} |
2533 DELTAREUSEALL = {b'always', b'samerevs', b'never', b'fulladd'} |
2530 |
2534 |
2531 def clone( |
2535 def clone( |
2532 self, |
2536 self, |
2533 tr, |
2537 tr, |
2534 destrevlog, |
2538 destrevlog, |
2576 In addition to the delta policy, the ``forcedeltabothparents`` |
2580 In addition to the delta policy, the ``forcedeltabothparents`` |
2577 argument controls whether to force compute deltas against both parents |
2581 argument controls whether to force compute deltas against both parents |
2578 for merges. By default, the current default is used. |
2582 for merges. By default, the current default is used. |
2579 """ |
2583 """ |
2580 if deltareuse not in self.DELTAREUSEALL: |
2584 if deltareuse not in self.DELTAREUSEALL: |
2581 raise ValueError(_('value for deltareuse invalid: %s') % deltareuse) |
2585 raise ValueError( |
2586 _(b'value for deltareuse invalid: %s') % deltareuse |
|
2587 ) |
|
2582 |
2588 |
2583 if len(destrevlog): |
2589 if len(destrevlog): |
2584 raise ValueError(_('destination revlog is not empty')) |
2590 raise ValueError(_(b'destination revlog is not empty')) |
2585 |
2591 |
2586 if getattr(self, 'filteredrevs', None): |
2592 if getattr(self, 'filteredrevs', None): |
2587 raise ValueError(_('source revlog has filtered revisions')) |
2593 raise ValueError(_(b'source revlog has filtered revisions')) |
2588 if getattr(destrevlog, 'filteredrevs', None): |
2594 if getattr(destrevlog, 'filteredrevs', None): |
2589 raise ValueError(_('destination revlog has filtered revisions')) |
2595 raise ValueError(_(b'destination revlog has filtered revisions')) |
2590 |
2596 |
2591 # lazydelta and lazydeltabase controls whether to reuse a cached delta, |
2597 # lazydelta and lazydeltabase controls whether to reuse a cached delta, |
2592 # if possible. |
2598 # if possible. |
2593 oldlazydelta = destrevlog._lazydelta |
2599 oldlazydelta = destrevlog._lazydelta |
2594 oldlazydeltabase = destrevlog._lazydeltabase |
2600 oldlazydeltabase = destrevlog._lazydeltabase |
2658 |
2664 |
2659 if not cachedelta: |
2665 if not cachedelta: |
2660 rawtext = self.rawdata(rev) |
2666 rawtext = self.rawdata(rev) |
2661 |
2667 |
2662 ifh = destrevlog.opener( |
2668 ifh = destrevlog.opener( |
2663 destrevlog.indexfile, 'a+', checkambig=False |
2669 destrevlog.indexfile, b'a+', checkambig=False |
2664 ) |
2670 ) |
2665 dfh = None |
2671 dfh = None |
2666 if not destrevlog._inline: |
2672 if not destrevlog._inline: |
2667 dfh = destrevlog.opener(destrevlog.datafile, 'a+') |
2673 dfh = destrevlog.opener(destrevlog.datafile, b'a+') |
2668 try: |
2674 try: |
2669 destrevlog._addrevision( |
2675 destrevlog._addrevision( |
2670 node, |
2676 node, |
2671 rawtext, |
2677 rawtext, |
2672 tr, |
2678 tr, |
2688 addrevisioncb(self, rev, node) |
2694 addrevisioncb(self, rev, node) |
2689 |
2695 |
2690 def censorrevision(self, tr, censornode, tombstone=b''): |
2696 def censorrevision(self, tr, censornode, tombstone=b''): |
2691 if (self.version & 0xFFFF) == REVLOGV0: |
2697 if (self.version & 0xFFFF) == REVLOGV0: |
2692 raise error.RevlogError( |
2698 raise error.RevlogError( |
2693 _('cannot censor with version %d revlogs') % self.version |
2699 _(b'cannot censor with version %d revlogs') % self.version |
2694 ) |
2700 ) |
2695 |
2701 |
2696 censorrev = self.rev(censornode) |
2702 censorrev = self.rev(censornode) |
2697 tombstone = storageutil.packmeta({b'censored': tombstone}, b'') |
2703 tombstone = storageutil.packmeta({b'censored': tombstone}, b'') |
2698 |
2704 |
2699 if len(tombstone) > self.rawsize(censorrev): |
2705 if len(tombstone) > self.rawsize(censorrev): |
2700 raise error.Abort( |
2706 raise error.Abort( |
2701 _('censor tombstone must be no longer than ' 'censored data') |
2707 _(b'censor tombstone must be no longer than ' b'censored data') |
2702 ) |
2708 ) |
2703 |
2709 |
2704 # Rewriting the revlog in place is hard. Our strategy for censoring is |
2710 # Rewriting the revlog in place is hard. Our strategy for censoring is |
2705 # to create a new revlog, copy all revisions to it, then replace the |
2711 # to create a new revlog, copy all revisions to it, then replace the |
2706 # revlogs on transaction close. |
2712 # revlogs on transaction close. |
2730 ) |
2736 ) |
2731 |
2737 |
2732 if newrl.deltaparent(rev) != nullrev: |
2738 if newrl.deltaparent(rev) != nullrev: |
2733 raise error.Abort( |
2739 raise error.Abort( |
2734 _( |
2740 _( |
2735 'censored revision stored as delta; ' |
2741 b'censored revision stored as delta; ' |
2736 'cannot censor' |
2742 b'cannot censor' |
2737 ), |
2743 ), |
2738 hint=_( |
2744 hint=_( |
2739 'censoring of revlogs is not ' |
2745 b'censoring of revlogs is not ' |
2740 'fully implemented; please report ' |
2746 b'fully implemented; please report ' |
2741 'this bug' |
2747 b'this bug' |
2742 ), |
2748 ), |
2743 ) |
2749 ) |
2744 continue |
2750 continue |
2745 |
2751 |
2746 if self.iscensored(rev): |
2752 if self.iscensored(rev): |
2747 if self.deltaparent(rev) != nullrev: |
2753 if self.deltaparent(rev) != nullrev: |
2748 raise error.Abort( |
2754 raise error.Abort( |
2749 _( |
2755 _( |
2750 'cannot censor due to censored ' |
2756 b'cannot censor due to censored ' |
2751 'revision having delta stored' |
2757 b'revision having delta stored' |
2752 ) |
2758 ) |
2753 ) |
2759 ) |
2754 rawtext = self._chunk(rev) |
2760 rawtext = self._chunk(rev) |
2755 else: |
2761 else: |
2756 rawtext = self.rawdata(rev) |
2762 rawtext = self.rawdata(rev) |
2757 |
2763 |
2758 newrl.addrawrevision( |
2764 newrl.addrawrevision( |
2759 rawtext, tr, self.linkrev(rev), p1, p2, node, self.flags(rev) |
2765 rawtext, tr, self.linkrev(rev), p1, p2, node, self.flags(rev) |
2760 ) |
2766 ) |
2761 |
2767 |
2762 tr.addbackup(self.indexfile, location='store') |
2768 tr.addbackup(self.indexfile, location=b'store') |
2763 if not self._inline: |
2769 if not self._inline: |
2764 tr.addbackup(self.datafile, location='store') |
2770 tr.addbackup(self.datafile, location=b'store') |
2765 |
2771 |
2766 self.opener.rename(newrl.indexfile, self.indexfile) |
2772 self.opener.rename(newrl.indexfile, self.indexfile) |
2767 if not self._inline: |
2773 if not self._inline: |
2768 self.opener.rename(newrl.datafile, self.datafile) |
2774 self.opener.rename(newrl.datafile, self.datafile) |
2769 |
2775 |
2776 Yields ``revlogproblem`` instances describing problems that are |
2782 Yields ``revlogproblem`` instances describing problems that are |
2777 found. |
2783 found. |
2778 """ |
2784 """ |
2779 dd, di = self.checksize() |
2785 dd, di = self.checksize() |
2780 if dd: |
2786 if dd: |
2781 yield revlogproblem(error=_('data length off by %d bytes') % dd) |
2787 yield revlogproblem(error=_(b'data length off by %d bytes') % dd) |
2782 if di: |
2788 if di: |
2783 yield revlogproblem(error=_('index contains %d extra bytes') % di) |
2789 yield revlogproblem(error=_(b'index contains %d extra bytes') % di) |
2784 |
2790 |
2785 version = self.version & 0xFFFF |
2791 version = self.version & 0xFFFF |
2786 |
2792 |
2787 # The verifier tells us what version revlog we should be. |
2793 # The verifier tells us what version revlog we should be. |
2788 if version != state['expectedversion']: |
2794 if version != state[b'expectedversion']: |
2789 yield revlogproblem( |
2795 yield revlogproblem( |
2790 warning=_("warning: '%s' uses revlog format %d; expected %d") |
2796 warning=_(b"warning: '%s' uses revlog format %d; expected %d") |
2791 % (self.indexfile, version, state['expectedversion']) |
2797 % (self.indexfile, version, state[b'expectedversion']) |
2792 ) |
2798 ) |
2793 |
2799 |
2794 state['skipread'] = set() |
2800 state[b'skipread'] = set() |
2795 |
2801 |
2796 for rev in self: |
2802 for rev in self: |
2797 node = self.node(rev) |
2803 node = self.node(rev) |
2798 |
2804 |
2799 # Verify contents. 4 cases to care about: |
2805 # Verify contents. 4 cases to care about: |
2843 # 1. length check: L1 == L2, in all cases. |
2849 # 1. length check: L1 == L2, in all cases. |
2844 # 2. hash check: depending on flag processor, we may need to |
2850 # 2. hash check: depending on flag processor, we may need to |
2845 # use either "text" (external), or "rawtext" (in revlog). |
2851 # use either "text" (external), or "rawtext" (in revlog). |
2846 |
2852 |
2847 try: |
2853 try: |
2848 skipflags = state.get('skipflags', 0) |
2854 skipflags = state.get(b'skipflags', 0) |
2849 if skipflags: |
2855 if skipflags: |
2850 skipflags &= self.flags(rev) |
2856 skipflags &= self.flags(rev) |
2851 |
2857 |
2852 if skipflags: |
2858 if skipflags: |
2853 state['skipread'].add(node) |
2859 state[b'skipread'].add(node) |
2854 else: |
2860 else: |
2855 # Side-effect: read content and verify hash. |
2861 # Side-effect: read content and verify hash. |
2856 self.revision(node) |
2862 self.revision(node) |
2857 |
2863 |
2858 l1 = self.rawsize(rev) |
2864 l1 = self.rawsize(rev) |
2859 l2 = len(self.rawdata(node)) |
2865 l2 = len(self.rawdata(node)) |
2860 |
2866 |
2861 if l1 != l2: |
2867 if l1 != l2: |
2862 yield revlogproblem( |
2868 yield revlogproblem( |
2863 error=_('unpacked size is %d, %d expected') % (l2, l1), |
2869 error=_(b'unpacked size is %d, %d expected') % (l2, l1), |
2864 node=node, |
2870 node=node, |
2865 ) |
2871 ) |
2866 |
2872 |
2867 except error.CensoredNodeError: |
2873 except error.CensoredNodeError: |
2868 if state['erroroncensored']: |
2874 if state[b'erroroncensored']: |
2869 yield revlogproblem( |
2875 yield revlogproblem( |
2870 error=_('censored file data'), node=node |
2876 error=_(b'censored file data'), node=node |
2871 ) |
2877 ) |
2872 state['skipread'].add(node) |
2878 state[b'skipread'].add(node) |
2873 except Exception as e: |
2879 except Exception as e: |
2874 yield revlogproblem( |
2880 yield revlogproblem( |
2875 error=_('unpacking %s: %s') |
2881 error=_(b'unpacking %s: %s') |
2876 % (short(node), stringutil.forcebytestr(e)), |
2882 % (short(node), stringutil.forcebytestr(e)), |
2877 node=node, |
2883 node=node, |
2878 ) |
2884 ) |
2879 state['skipread'].add(node) |
2885 state[b'skipread'].add(node) |
2880 |
2886 |
2881 def storageinfo( |
2887 def storageinfo( |
2882 self, |
2888 self, |
2883 exclusivefiles=False, |
2889 exclusivefiles=False, |
2884 sharedfiles=False, |
2890 sharedfiles=False, |
2887 storedsize=False, |
2893 storedsize=False, |
2888 ): |
2894 ): |
2889 d = {} |
2895 d = {} |
2890 |
2896 |
2891 if exclusivefiles: |
2897 if exclusivefiles: |
2892 d['exclusivefiles'] = [(self.opener, self.indexfile)] |
2898 d[b'exclusivefiles'] = [(self.opener, self.indexfile)] |
2893 if not self._inline: |
2899 if not self._inline: |
2894 d['exclusivefiles'].append((self.opener, self.datafile)) |
2900 d[b'exclusivefiles'].append((self.opener, self.datafile)) |
2895 |
2901 |
2896 if sharedfiles: |
2902 if sharedfiles: |
2897 d['sharedfiles'] = [] |
2903 d[b'sharedfiles'] = [] |
2898 |
2904 |
2899 if revisionscount: |
2905 if revisionscount: |
2900 d['revisionscount'] = len(self) |
2906 d[b'revisionscount'] = len(self) |
2901 |
2907 |
2902 if trackedsize: |
2908 if trackedsize: |
2903 d['trackedsize'] = sum(map(self.rawsize, iter(self))) |
2909 d[b'trackedsize'] = sum(map(self.rawsize, iter(self))) |
2904 |
2910 |
2905 if storedsize: |
2911 if storedsize: |
2906 d['storedsize'] = sum( |
2912 d[b'storedsize'] = sum( |
2907 self.opener.stat(path).st_size for path in self.files() |
2913 self.opener.stat(path).st_size for path in self.files() |
2908 ) |
2914 ) |
2909 |
2915 |
2910 return d |
2916 return d |