Show More
@@ -459,8 +459,9 b' class changelog(revlog.revlog):' | |||||
459 | self.opener = _delayopener( |
|
459 | self.opener = _delayopener( | |
460 | self._realopener, self._indexfile, self._delaybuf |
|
460 | self._realopener, self._indexfile, self._delaybuf | |
461 | ) |
|
461 | ) | |
462 |
self._ |
|
462 | self._inner.opener = self.opener | |
463 |
self._segmentfile |
|
463 | self._inner._segmentfile.opener = self.opener | |
|
464 | self._inner._segmentfile_sidedata.opener = self.opener | |||
464 | self._delayed = True |
|
465 | self._delayed = True | |
465 | tr.addpending(b'cl-%i' % id(self), self._writepending) |
|
466 | tr.addpending(b'cl-%i' % id(self), self._writepending) | |
466 | tr.addfinalize(b'cl-%i' % id(self), self._finalize) |
|
467 | tr.addfinalize(b'cl-%i' % id(self), self._finalize) | |
@@ -469,8 +470,9 b' class changelog(revlog.revlog):' | |||||
469 | """finalize index updates""" |
|
470 | """finalize index updates""" | |
470 | self._delayed = False |
|
471 | self._delayed = False | |
471 | self.opener = self._realopener |
|
472 | self.opener = self._realopener | |
472 |
self._ |
|
473 | self._inner.opener = self.opener | |
473 |
self._segmentfile |
|
474 | self._inner._segmentfile.opener = self.opener | |
|
475 | self._inner._segmentfile_sidedata.opener = self.opener | |||
474 | # move redirected index data back into place |
|
476 | # move redirected index data back into place | |
475 | if self._docket is not None: |
|
477 | if self._docket is not None: | |
476 | self._write_docket(tr) |
|
478 | self._write_docket(tr) | |
@@ -510,8 +512,9 b' class changelog(revlog.revlog):' | |||||
510 | self._delaybuf = None |
|
512 | self._delaybuf = None | |
511 | self._divert = True |
|
513 | self._divert = True | |
512 | self.opener = _divertopener(self._realopener, self._indexfile) |
|
514 | self.opener = _divertopener(self._realopener, self._indexfile) | |
513 |
self._ |
|
515 | self._inner.opener = self.opener | |
514 |
self._segmentfile |
|
516 | self._inner._segmentfile.opener = self.opener | |
|
517 | self._inner._segmentfile_sidedata.opener = self.opener | |||
515 |
|
518 | |||
516 | if self._divert: |
|
519 | if self._divert: | |
517 | return True |
|
520 | return True |
@@ -337,6 +337,178 b' class DeltaConfig(_Config):' | |||||
337 | lazy_delta_base = attr.ib(default=False) |
|
337 | lazy_delta_base = attr.ib(default=False) | |
338 |
|
338 | |||
339 |
|
339 | |||
|
340 | class _InnerRevlog: | |||
|
341 | """An inner layer of the revlog object | |||
|
342 | ||||
|
343 | That layer exist to be able to delegate some operation to Rust, its | |||
|
344 | boundaries are arbitrary and based on what we can delegate to Rust. | |||
|
345 | """ | |||
|
346 | ||||
|
347 | def __init__( | |||
|
348 | self, | |||
|
349 | opener, | |||
|
350 | index, | |||
|
351 | index_file, | |||
|
352 | data_file, | |||
|
353 | sidedata_file, | |||
|
354 | inline, | |||
|
355 | data_config, | |||
|
356 | chunk_cache, | |||
|
357 | ): | |||
|
358 | self.opener = opener | |||
|
359 | self.index = index | |||
|
360 | ||||
|
361 | self.index_file = index_file | |||
|
362 | self.data_file = data_file | |||
|
363 | self.sidedata_file = sidedata_file | |||
|
364 | self.inline = inline | |||
|
365 | self.data_config = data_config | |||
|
366 | ||||
|
367 | # index | |||
|
368 | ||||
|
369 | # 3-tuple of file handles being used for active writing. | |||
|
370 | self._writinghandles = None | |||
|
371 | ||||
|
372 | self._segmentfile = randomaccessfile.randomaccessfile( | |||
|
373 | self.opener, | |||
|
374 | (self.index_file if self.inline else self.data_file), | |||
|
375 | self.data_config.chunk_cache_size, | |||
|
376 | chunk_cache, | |||
|
377 | ) | |||
|
378 | self._segmentfile_sidedata = randomaccessfile.randomaccessfile( | |||
|
379 | self.opener, | |||
|
380 | self.sidedata_file, | |||
|
381 | self.data_config.chunk_cache_size, | |||
|
382 | ) | |||
|
383 | ||||
|
384 | # Derived from index values. | |||
|
385 | ||||
|
386 | def start(self, rev): | |||
|
387 | """the offset of the data chunk for this revision""" | |||
|
388 | return int(self.index[rev][0] >> 16) | |||
|
389 | ||||
|
390 | def length(self, rev): | |||
|
391 | """the length of the data chunk for this revision""" | |||
|
392 | return self.index[rev][1] | |||
|
393 | ||||
|
394 | def end(self, rev): | |||
|
395 | """the end of the data chunk for this revision""" | |||
|
396 | return self.start(rev) + self.length(rev) | |||
|
397 | ||||
|
398 | @contextlib.contextmanager | |||
|
399 | def reading(self): | |||
|
400 | """Context manager that keeps data and sidedata files open for reading""" | |||
|
401 | if len(self.index) == 0: | |||
|
402 | yield # nothing to be read | |||
|
403 | else: | |||
|
404 | with self._segmentfile.reading(): | |||
|
405 | with self._segmentfile_sidedata.reading(): | |||
|
406 | yield | |||
|
407 | ||||
|
408 | @property | |||
|
409 | def is_writing(self): | |||
|
410 | """True is a writing context is open""" | |||
|
411 | return self._writinghandles is not None | |||
|
412 | ||||
|
413 | @contextlib.contextmanager | |||
|
414 | def writing(self, transaction, data_end=None, sidedata_end=None): | |||
|
415 | """Open the revlog files for writing | |||
|
416 | ||||
|
417 | Add content to a revlog should be done within such context. | |||
|
418 | """ | |||
|
419 | if self.is_writing: | |||
|
420 | yield | |||
|
421 | else: | |||
|
422 | ifh = dfh = sdfh = None | |||
|
423 | try: | |||
|
424 | r = len(self.index) | |||
|
425 | # opening the data file. | |||
|
426 | dsize = 0 | |||
|
427 | if r: | |||
|
428 | dsize = self.end(r - 1) | |||
|
429 | dfh = None | |||
|
430 | if not self.inline: | |||
|
431 | try: | |||
|
432 | dfh = self.opener(self.data_file, mode=b"r+") | |||
|
433 | if data_end is None: | |||
|
434 | dfh.seek(0, os.SEEK_END) | |||
|
435 | else: | |||
|
436 | dfh.seek(data_end, os.SEEK_SET) | |||
|
437 | except FileNotFoundError: | |||
|
438 | dfh = self.opener(self.data_file, mode=b"w+") | |||
|
439 | transaction.add(self.data_file, dsize) | |||
|
440 | if self.sidedata_file is not None: | |||
|
441 | assert sidedata_end is not None | |||
|
442 | # revlog-v2 does not inline, help Pytype | |||
|
443 | assert dfh is not None | |||
|
444 | try: | |||
|
445 | sdfh = self.opener(self.sidedata_file, mode=b"r+") | |||
|
446 | dfh.seek(sidedata_end, os.SEEK_SET) | |||
|
447 | except FileNotFoundError: | |||
|
448 | sdfh = self.opener(self.sidedata_file, mode=b"w+") | |||
|
449 | transaction.add(self.sidedata_file, sidedata_end) | |||
|
450 | ||||
|
451 | # opening the index file. | |||
|
452 | isize = r * self.index.entry_size | |||
|
453 | ifh = self.__index_write_fp() | |||
|
454 | if self.inline: | |||
|
455 | transaction.add(self.index_file, dsize + isize) | |||
|
456 | else: | |||
|
457 | transaction.add(self.index_file, isize) | |||
|
458 | # exposing all file handle for writing. | |||
|
459 | self._writinghandles = (ifh, dfh, sdfh) | |||
|
460 | self._segmentfile.writing_handle = ifh if self.inline else dfh | |||
|
461 | self._segmentfile_sidedata.writing_handle = sdfh | |||
|
462 | yield | |||
|
463 | finally: | |||
|
464 | self._writinghandles = None | |||
|
465 | self._segmentfile.writing_handle = None | |||
|
466 | self._segmentfile_sidedata.writing_handle = None | |||
|
467 | if dfh is not None: | |||
|
468 | dfh.close() | |||
|
469 | if sdfh is not None: | |||
|
470 | sdfh.close() | |||
|
471 | # closing the index file last to avoid exposing referent to | |||
|
472 | # potential unflushed data content. | |||
|
473 | if ifh is not None: | |||
|
474 | ifh.close() | |||
|
475 | ||||
|
476 | def __index_write_fp(self, index_end=None): | |||
|
477 | """internal method to open the index file for writing | |||
|
478 | ||||
|
479 | You should not use this directly and use `_writing` instead | |||
|
480 | """ | |||
|
481 | try: | |||
|
482 | f = self.opener( | |||
|
483 | self.index_file, | |||
|
484 | mode=b"r+", | |||
|
485 | checkambig=self.data_config.check_ambig, | |||
|
486 | ) | |||
|
487 | if index_end is None: | |||
|
488 | f.seek(0, os.SEEK_END) | |||
|
489 | else: | |||
|
490 | f.seek(index_end, os.SEEK_SET) | |||
|
491 | return f | |||
|
492 | except FileNotFoundError: | |||
|
493 | return self.opener( | |||
|
494 | self.index_file, | |||
|
495 | mode=b"w+", | |||
|
496 | checkambig=self.data_config.check_ambig, | |||
|
497 | ) | |||
|
498 | ||||
|
499 | def __index_new_fp(self): | |||
|
500 | """internal method to create a new index file for writing | |||
|
501 | ||||
|
502 | You should not use this unless you are upgrading from inline revlog | |||
|
503 | """ | |||
|
504 | return self.opener( | |||
|
505 | self.index_file, | |||
|
506 | mode=b"w", | |||
|
507 | checkambig=self.data_config.check_ambig, | |||
|
508 | atomictemp=True, | |||
|
509 | ) | |||
|
510 | ||||
|
511 | ||||
340 | class revlog: |
|
512 | class revlog: | |
341 | """ |
|
513 | """ | |
342 | the underlying revision storage object |
|
514 | the underlying revision storage object | |
@@ -477,13 +649,11 b' class revlog:' | |||||
477 | # Make copy of flag processors so each revlog instance can support |
|
649 | # Make copy of flag processors so each revlog instance can support | |
478 | # custom flags. |
|
650 | # custom flags. | |
479 | self._flagprocessors = dict(flagutil.flagprocessors) |
|
651 | self._flagprocessors = dict(flagutil.flagprocessors) | |
480 |
|
||||
481 | # 3-tuple of file handles being used for active writing. |
|
|||
482 | self._writinghandles = None |
|
|||
483 | # prevent nesting of addgroup |
|
652 | # prevent nesting of addgroup | |
484 | self._adding_group = None |
|
653 | self._adding_group = None | |
485 |
|
654 | |||
486 | self._loadindex() |
|
655 | chunk_cache = self._loadindex() | |
|
656 | self._load_inner(chunk_cache) | |||
487 |
|
657 | |||
488 | self._concurrencychecker = concurrencychecker |
|
658 | self._concurrencychecker = concurrencychecker | |
489 |
|
659 | |||
@@ -1007,22 +1177,25 b' class revlog:' | |||||
1007 | _(b"index %s is corrupted") % self.display_id |
|
1177 | _(b"index %s is corrupted") % self.display_id | |
1008 | ) |
|
1178 | ) | |
1009 | self.index = index |
|
1179 | self.index = index | |
1010 | self._segmentfile = randomaccessfile.randomaccessfile( |
|
|||
1011 | self.opener, |
|
|||
1012 | (self._indexfile if self._inline else self._datafile), |
|
|||
1013 | self.data_config.chunk_cache_size, |
|
|||
1014 | chunkcache, |
|
|||
1015 | ) |
|
|||
1016 | self._segmentfile_sidedata = randomaccessfile.randomaccessfile( |
|
|||
1017 | self.opener, |
|
|||
1018 | self._sidedatafile, |
|
|||
1019 | self.data_config.chunk_cache_size, |
|
|||
1020 | ) |
|
|||
1021 | # revnum -> (chain-length, sum-delta-length) |
|
1180 | # revnum -> (chain-length, sum-delta-length) | |
1022 | self._chaininfocache = util.lrucachedict(500) |
|
1181 | self._chaininfocache = util.lrucachedict(500) | |
1023 | # revlog header -> revlog compressor |
|
1182 | # revlog header -> revlog compressor | |
1024 | self._decompressors = {} |
|
1183 | self._decompressors = {} | |
1025 |
|
1184 | |||
|
1185 | return chunkcache | |||
|
1186 | ||||
|
1187 | def _load_inner(self, chunk_cache): | |||
|
1188 | self._inner = _InnerRevlog( | |||
|
1189 | opener=self.opener, | |||
|
1190 | index=self.index, | |||
|
1191 | index_file=self._indexfile, | |||
|
1192 | data_file=self._datafile, | |||
|
1193 | sidedata_file=self._sidedatafile, | |||
|
1194 | inline=self._inline, | |||
|
1195 | data_config=self.data_config, | |||
|
1196 | chunk_cache=chunk_cache, | |||
|
1197 | ) | |||
|
1198 | ||||
1026 | def get_revlog(self): |
|
1199 | def get_revlog(self): | |
1027 | """simple function to mirror API of other not-really-revlog API""" |
|
1200 | """simple function to mirror API of other not-really-revlog API""" | |
1028 | return self |
|
1201 | return self | |
@@ -1073,35 +1246,6 b' class revlog:' | |||||
1073 | c = self._get_decompressor(t) |
|
1246 | c = self._get_decompressor(t) | |
1074 | return c.decompress |
|
1247 | return c.decompress | |
1075 |
|
1248 | |||
1076 | def __index_write_fp(self): |
|
|||
1077 | # You should not use this directly and use `_writing` instead |
|
|||
1078 | try: |
|
|||
1079 | f = self.opener( |
|
|||
1080 | self._indexfile, |
|
|||
1081 | mode=b"r+", |
|
|||
1082 | checkambig=self.data_config.check_ambig, |
|
|||
1083 | ) |
|
|||
1084 | if self._docket is None: |
|
|||
1085 | f.seek(0, os.SEEK_END) |
|
|||
1086 | else: |
|
|||
1087 | f.seek(self._docket.index_end, os.SEEK_SET) |
|
|||
1088 | return f |
|
|||
1089 | except FileNotFoundError: |
|
|||
1090 | return self.opener( |
|
|||
1091 | self._indexfile, |
|
|||
1092 | mode=b"w+", |
|
|||
1093 | checkambig=self.data_config.check_ambig, |
|
|||
1094 | ) |
|
|||
1095 |
|
||||
1096 | def __index_new_fp(self): |
|
|||
1097 | # You should not use this unless you are upgrading from inline revlog |
|
|||
1098 | return self.opener( |
|
|||
1099 | self._indexfile, |
|
|||
1100 | mode=b"w", |
|
|||
1101 | checkambig=self.data_config.check_ambig, |
|
|||
1102 | atomictemp=True, |
|
|||
1103 | ) |
|
|||
1104 |
|
||||
1105 | def _datafp(self, mode=b'r'): |
|
1249 | def _datafp(self, mode=b'r'): | |
1106 | """file object for the revlog's data file""" |
|
1250 | """file object for the revlog's data file""" | |
1107 | return self.opener(self._datafile, mode=mode) |
|
1251 | return self.opener(self._datafile, mode=mode) | |
@@ -1160,8 +1304,8 b' class revlog:' | |||||
1160 | """Clear in-memory caches""" |
|
1304 | """Clear in-memory caches""" | |
1161 | self._revisioncache = None |
|
1305 | self._revisioncache = None | |
1162 | self._chainbasecache.clear() |
|
1306 | self._chainbasecache.clear() | |
1163 | self._segmentfile.clear_cache() |
|
1307 | self._inner._segmentfile.clear_cache() | |
1164 | self._segmentfile_sidedata.clear_cache() |
|
1308 | self._inner._segmentfile_sidedata.clear_cache() | |
1165 | self._pcache = {} |
|
1309 | self._pcache = {} | |
1166 | self._nodemap_docket = None |
|
1310 | self._nodemap_docket = None | |
1167 | self.index.clearcaches() |
|
1311 | self.index.clearcaches() | |
@@ -2041,7 +2185,7 b' class revlog:' | |||||
2041 | end += (endrev + 1) * self.index.entry_size |
|
2185 | end += (endrev + 1) * self.index.entry_size | |
2042 | length = end - start |
|
2186 | length = end - start | |
2043 |
|
2187 | |||
2044 | return start, self._segmentfile.read_chunk(start, length) |
|
2188 | return start, self._inner._segmentfile.read_chunk(start, length) | |
2045 |
|
2189 | |||
2046 | def _chunk(self, rev): |
|
2190 | def _chunk(self, rev): | |
2047 | """Obtain a single decompressed chunk for a revision. |
|
2191 | """Obtain a single decompressed chunk for a revision. | |
@@ -2318,7 +2462,7 b' class revlog:' | |||||
2318 | m = FILE_TOO_SHORT_MSG % (filename, length, offset, end) |
|
2462 | m = FILE_TOO_SHORT_MSG % (filename, length, offset, end) | |
2319 | raise error.RevlogError(m) |
|
2463 | raise error.RevlogError(m) | |
2320 |
|
2464 | |||
2321 | comp_segment = self._segmentfile_sidedata.read_chunk( |
|
2465 | comp_segment = self._inner._segmentfile_sidedata.read_chunk( | |
2322 | sidedata_offset, sidedata_size |
|
2466 | sidedata_offset, sidedata_size | |
2323 | ) |
|
2467 | ) | |
2324 |
|
2468 | |||
@@ -2423,15 +2567,15 b' class revlog:' | |||||
2423 | tr.add(self._datafile, 0) |
|
2567 | tr.add(self._datafile, 0) | |
2424 |
|
2568 | |||
2425 | existing_handles = False |
|
2569 | existing_handles = False | |
2426 | if self._writinghandles is not None: |
|
2570 | if self._inner._writinghandles is not None: | |
2427 | existing_handles = True |
|
2571 | existing_handles = True | |
2428 | fp = self._writinghandles[0] |
|
2572 | fp = self._inner._writinghandles[0] | |
2429 | fp.flush() |
|
2573 | fp.flush() | |
2430 | fp.close() |
|
2574 | fp.close() | |
2431 | # We can't use the cached file handle after close(). So prevent |
|
2575 | # We can't use the cached file handle after close(). So prevent | |
2432 | # its usage. |
|
2576 | # its usage. | |
2433 | self._writinghandles = None |
|
2577 | self._inner._writinghandles = None | |
2434 | self._segmentfile.writing_handle = None |
|
2578 | self._inner._segmentfile.writing_handle = None | |
2435 | # No need to deal with sidedata writing handle as it is only |
|
2579 | # No need to deal with sidedata writing handle as it is only | |
2436 | # relevant with revlog-v2 which is never inline, not reaching |
|
2580 | # relevant with revlog-v2 which is never inline, not reaching | |
2437 | # this code |
|
2581 | # this code | |
@@ -2451,11 +2595,13 b' class revlog:' | |||||
2451 | maybe_self = weak_self() |
|
2595 | maybe_self = weak_self() | |
2452 | if maybe_self is not None: |
|
2596 | if maybe_self is not None: | |
2453 | maybe_self._indexfile = old_index_file_path |
|
2597 | maybe_self._indexfile = old_index_file_path | |
|
2598 | maybe_self._inner.index_file = maybe_self._indexfile | |||
2454 |
|
2599 | |||
2455 | def abort_callback(tr): |
|
2600 | def abort_callback(tr): | |
2456 | maybe_self = weak_self() |
|
2601 | maybe_self = weak_self() | |
2457 | if maybe_self is not None: |
|
2602 | if maybe_self is not None: | |
2458 | maybe_self._indexfile = old_index_file_path |
|
2603 | maybe_self._indexfile = old_index_file_path | |
|
2604 | maybe_self._inner.index_file = old_index_file_path | |||
2459 |
|
2605 | |||
2460 | tr.registertmp(new_index_file_path) |
|
2606 | tr.registertmp(new_index_file_path) | |
2461 | if self.target[1] is not None: |
|
2607 | if self.target[1] is not None: | |
@@ -2475,9 +2621,11 b' class revlog:' | |||||
2475 |
|
2621 | |||
2476 | if side_write: |
|
2622 | if side_write: | |
2477 | self._indexfile = new_index_file_path |
|
2623 | self._indexfile = new_index_file_path | |
2478 | with self.__index_new_fp() as fp: |
|
2624 | self._inner.index_file = self._indexfile | |
|
2625 | with self._inner._InnerRevlog__index_new_fp() as fp: | |||
2479 | self._format_flags &= ~FLAG_INLINE_DATA |
|
2626 | self._format_flags &= ~FLAG_INLINE_DATA | |
2480 | self._inline = False |
|
2627 | self._inline = False | |
|
2628 | self._inner.inline = False | |||
2481 | for i in self: |
|
2629 | for i in self: | |
2482 | e = self.index.entry_binary(i) |
|
2630 | e = self.index.entry_binary(i) | |
2483 | if i == 0 and self._docket is None: |
|
2631 | if i == 0 and self._docket is None: | |
@@ -2492,7 +2640,7 b' class revlog:' | |||||
2492 | # index when we exit the context manager |
|
2640 | # index when we exit the context manager | |
2493 |
|
2641 | |||
2494 | nodemaputil.setup_persistent_nodemap(tr, self) |
|
2642 | nodemaputil.setup_persistent_nodemap(tr, self) | |
2495 | self._segmentfile = randomaccessfile.randomaccessfile( |
|
2643 | self._inner._segmentfile = randomaccessfile.randomaccessfile( | |
2496 | self.opener, |
|
2644 | self.opener, | |
2497 | self._datafile, |
|
2645 | self._datafile, | |
2498 | self.data_config.chunk_cache_size, |
|
2646 | self.data_config.chunk_cache_size, | |
@@ -2500,9 +2648,14 b' class revlog:' | |||||
2500 |
|
2648 | |||
2501 | if existing_handles: |
|
2649 | if existing_handles: | |
2502 | # switched from inline to conventional reopen the index |
|
2650 | # switched from inline to conventional reopen the index | |
2503 | ifh = self.__index_write_fp() |
|
2651 | index_end = None | |
2504 |
self._ |
|
2652 | if self._docket is not None: | |
2505 | self._segmentfile.writing_handle = new_dfh |
|
2653 | index_end = self._docket.index_end | |
|
2654 | ifh = self._inner._InnerRevlog__index_write_fp( | |||
|
2655 | index_end=index_end | |||
|
2656 | ) | |||
|
2657 | self._inner._writinghandles = (ifh, new_dfh, None) | |||
|
2658 | self._inner._segmentfile.writing_handle = new_dfh | |||
2506 | new_dfh = None |
|
2659 | new_dfh = None | |
2507 | # No need to deal with sidedata writing handle as it is only |
|
2660 | # No need to deal with sidedata writing handle as it is only | |
2508 | # relevant with revlog-v2 which is never inline, not reaching |
|
2661 | # relevant with revlog-v2 which is never inline, not reaching | |
@@ -2516,12 +2669,7 b' class revlog:' | |||||
2516 |
|
2669 | |||
2517 | @contextlib.contextmanager |
|
2670 | @contextlib.contextmanager | |
2518 | def reading(self): |
|
2671 | def reading(self): | |
2519 | """Context manager that keeps data and sidedata files open for reading""" |
|
2672 | with self._inner.reading(): | |
2520 | if len(self.index) == 0: |
|
|||
2521 | yield # nothing to be read |
|
|||
2522 | else: |
|
|||
2523 | with self._segmentfile.reading(): |
|
|||
2524 | with self._segmentfile_sidedata.reading(): |
|
|||
2525 |
|
|
2673 | yield | |
2526 |
|
2674 | |||
2527 | @contextlib.contextmanager |
|
2675 | @contextlib.contextmanager | |
@@ -2530,65 +2678,22 b' class revlog:' | |||||
2530 | msg = b'try to write in a `trypending` revlog: %s' |
|
2678 | msg = b'try to write in a `trypending` revlog: %s' | |
2531 | msg %= self.display_id |
|
2679 | msg %= self.display_id | |
2532 | raise error.ProgrammingError(msg) |
|
2680 | raise error.ProgrammingError(msg) | |
2533 |
if self._ |
|
2681 | if self._inner.is_writing: | |
2534 | yield |
|
2682 | yield | |
2535 | else: |
|
2683 | else: | |
2536 |
|
|
2684 | data_end = None | |
2537 | try: |
|
2685 | sidedata_end = None | |
2538 | r = len(self) |
|
2686 | if self._docket is not None: | |
2539 | # opening the data file. |
|
2687 | data_end = self._docket.data_end | |
2540 | dsize = 0 |
|
2688 | sidedata_end = self._docket.sidedata_end | |
2541 | if r: |
|
2689 | with self._inner.writing( | |
2542 | dsize = self.end(r - 1) |
|
2690 | transaction, | |
2543 |
d |
|
2691 | data_end=data_end, | |
2544 | if not self._inline: |
|
2692 | sidedata_end=sidedata_end, | |
2545 |
|
|
2693 | ): | |
2546 | dfh = self._datafp(b"r+") |
|
|||
2547 | if self._docket is None: |
|
|||
2548 | dfh.seek(0, os.SEEK_END) |
|
|||
2549 | else: |
|
|||
2550 | dfh.seek(self._docket.data_end, os.SEEK_SET) |
|
|||
2551 | except FileNotFoundError: |
|
|||
2552 | dfh = self._datafp(b"w+") |
|
|||
2553 | transaction.add(self._datafile, dsize) |
|
|||
2554 | if self._sidedatafile is not None: |
|
|||
2555 | # revlog-v2 does not inline, help Pytype |
|
|||
2556 | assert dfh is not None |
|
|||
2557 | try: |
|
|||
2558 | sdfh = self.opener(self._sidedatafile, mode=b"r+") |
|
|||
2559 | dfh.seek(self._docket.sidedata_end, os.SEEK_SET) |
|
|||
2560 | except FileNotFoundError: |
|
|||
2561 | sdfh = self.opener(self._sidedatafile, mode=b"w+") |
|
|||
2562 | transaction.add( |
|
|||
2563 | self._sidedatafile, self._docket.sidedata_end |
|
|||
2564 | ) |
|
|||
2565 |
|
||||
2566 | # opening the index file. |
|
|||
2567 | isize = r * self.index.entry_size |
|
|||
2568 | ifh = self.__index_write_fp() |
|
|||
2569 | if self._inline: |
|
|||
2570 | transaction.add(self._indexfile, dsize + isize) |
|
|||
2571 | else: |
|
|||
2572 | transaction.add(self._indexfile, isize) |
|
|||
2573 | # exposing all file handle for writing. |
|
|||
2574 | self._writinghandles = (ifh, dfh, sdfh) |
|
|||
2575 | self._segmentfile.writing_handle = ifh if self._inline else dfh |
|
|||
2576 | self._segmentfile_sidedata.writing_handle = sdfh |
|
|||
2577 | yield |
|
2694 | yield | |
2578 | if self._docket is not None: |
|
2695 | if self._docket is not None: | |
2579 | self._write_docket(transaction) |
|
2696 | self._write_docket(transaction) | |
2580 | finally: |
|
|||
2581 | self._writinghandles = None |
|
|||
2582 | self._segmentfile.writing_handle = None |
|
|||
2583 | self._segmentfile_sidedata.writing_handle = None |
|
|||
2584 | if dfh is not None: |
|
|||
2585 | dfh.close() |
|
|||
2586 | if sdfh is not None: |
|
|||
2587 | sdfh.close() |
|
|||
2588 | # closing the index file last to avoid exposing referent to |
|
|||
2589 | # potential unflushed data content. |
|
|||
2590 | if ifh is not None: |
|
|||
2591 | ifh.close() |
|
|||
2592 |
|
2697 | |||
2593 | def _write_docket(self, transaction): |
|
2698 | def _write_docket(self, transaction): | |
2594 | """write the current docket on disk |
|
2699 | """write the current docket on disk | |
@@ -2811,7 +2916,7 b' class revlog:' | |||||
2811 | raise error.RevlogError( |
|
2916 | raise error.RevlogError( | |
2812 | _(b"%s: attempt to add wdir revision") % self.display_id |
|
2917 | _(b"%s: attempt to add wdir revision") % self.display_id | |
2813 | ) |
|
2918 | ) | |
2814 | if self._writinghandles is None: |
|
2919 | if self._inner._writinghandles is None: | |
2815 | msg = b'adding revision outside `revlog._writing` context' |
|
2920 | msg = b'adding revision outside `revlog._writing` context' | |
2816 | raise error.ProgrammingError(msg) |
|
2921 | raise error.ProgrammingError(msg) | |
2817 |
|
2922 | |||
@@ -2823,7 +2928,7 b' class revlog:' | |||||
2823 | offset = self._get_data_offset(prev) |
|
2928 | offset = self._get_data_offset(prev) | |
2824 |
|
2929 | |||
2825 | if self._concurrencychecker: |
|
2930 | if self._concurrencychecker: | |
2826 | ifh, dfh, sdfh = self._writinghandles |
|
2931 | ifh, dfh, sdfh = self._inner._writinghandles | |
2827 | # XXX no checking for the sidedata file |
|
2932 | # XXX no checking for the sidedata file | |
2828 | if self._inline: |
|
2933 | if self._inline: | |
2829 | # offset is "as if" it were in the .d file, so we need to add on |
|
2934 | # offset is "as if" it were in the .d file, so we need to add on | |
@@ -3007,10 +3112,10 b' class revlog:' | |||||
3007 | # Note: This is likely not necessary on Python 3. However, because |
|
3112 | # Note: This is likely not necessary on Python 3. However, because | |
3008 | # the file handle is reused for reads and may be seeked there, we need |
|
3113 | # the file handle is reused for reads and may be seeked there, we need | |
3009 | # to be careful before changing this. |
|
3114 | # to be careful before changing this. | |
3010 | if self._writinghandles is None: |
|
3115 | if self._inner._writinghandles is None: | |
3011 | msg = b'adding revision outside `revlog._writing` context' |
|
3116 | msg = b'adding revision outside `revlog._writing` context' | |
3012 | raise error.ProgrammingError(msg) |
|
3117 | raise error.ProgrammingError(msg) | |
3013 | ifh, dfh, sdfh = self._writinghandles |
|
3118 | ifh, dfh, sdfh = self._inner._writinghandles | |
3014 | if self._docket is None: |
|
3119 | if self._docket is None: | |
3015 | ifh.seek(0, os.SEEK_END) |
|
3120 | ifh.seek(0, os.SEEK_END) | |
3016 | else: |
|
3121 | else: | |
@@ -3045,9 +3150,9 b' class revlog:' | |||||
3045 | self._enforceinlinesize(transaction) |
|
3150 | self._enforceinlinesize(transaction) | |
3046 | if self._docket is not None: |
|
3151 | if self._docket is not None: | |
3047 | # revlog-v2 always has 3 writing handles, help Pytype |
|
3152 | # revlog-v2 always has 3 writing handles, help Pytype | |
3048 | wh1 = self._writinghandles[0] |
|
3153 | wh1 = self._inner._writinghandles[0] | |
3049 | wh2 = self._writinghandles[1] |
|
3154 | wh2 = self._inner._writinghandles[1] | |
3050 | wh3 = self._writinghandles[2] |
|
3155 | wh3 = self._inner._writinghandles[2] | |
3051 | assert wh1 is not None |
|
3156 | assert wh1 is not None | |
3052 | assert wh2 is not None |
|
3157 | assert wh2 is not None | |
3053 | assert wh3 is not None |
|
3158 | assert wh3 is not None | |
@@ -3259,8 +3364,8 b' class revlog:' | |||||
3259 | # then reset internal state in memory to forget those revisions |
|
3364 | # then reset internal state in memory to forget those revisions | |
3260 | self._revisioncache = None |
|
3365 | self._revisioncache = None | |
3261 | self._chaininfocache = util.lrucachedict(500) |
|
3366 | self._chaininfocache = util.lrucachedict(500) | |
3262 | self._segmentfile.clear_cache() |
|
3367 | self._inner._segmentfile.clear_cache() | |
3263 | self._segmentfile_sidedata.clear_cache() |
|
3368 | self._inner._segmentfile_sidedata.clear_cache() | |
3264 |
|
3369 | |||
3265 | del self.index[rev:-1] |
|
3370 | del self.index[rev:-1] | |
3266 |
|
3371 | |||
@@ -3723,7 +3828,7 b' class revlog:' | |||||
3723 | new_entries = [] |
|
3828 | new_entries = [] | |
3724 | # append the new sidedata |
|
3829 | # append the new sidedata | |
3725 | with self._writing(transaction): |
|
3830 | with self._writing(transaction): | |
3726 | ifh, dfh, sdfh = self._writinghandles |
|
3831 | ifh, dfh, sdfh = self._inner._writinghandles | |
3727 | dfh.seek(self._docket.sidedata_end, os.SEEK_SET) |
|
3832 | dfh.seek(self._docket.sidedata_end, os.SEEK_SET) | |
3728 |
|
3833 | |||
3729 | current_offset = sdfh.tell() |
|
3834 | current_offset = sdfh.tell() |
General Comments 0
You need to be logged in to leave comments.
Login now