--- a/mercurial/changelog.py Thu Oct 26 05:37:37 2023 +0200
+++ b/mercurial/changelog.py Tue Oct 24 11:08:49 2023 +0200
@@ -27,7 +27,6 @@
from .revlogutils import (
constants as revlog_constants,
flagutil,
- randomaccessfile,
)
_defaultextra = {b'branch': b'default'}
@@ -92,38 +91,6 @@
return b'\n'.join([l.rstrip() for l in desc.splitlines()]).strip(b'\n')
-class _divertopener:
- def __init__(self, opener, target):
- self._opener = opener
- self._target = target
-
- def __call__(self, name, mode=b'r', checkambig=False, **kwargs):
- if name != self._target:
- return self._opener(name, mode, **kwargs)
- return self._opener(name + b".a", mode, **kwargs)
-
- def __getattr__(self, attr):
- return getattr(self._opener, attr)
-
-
-class _delayopener:
- """build an opener that stores chunks in 'buf' instead of 'target'"""
-
- def __init__(self, opener, target, buf):
- self._opener = opener
- self._target = target
- self._buf = buf
-
- def __call__(self, name, mode=b'r', checkambig=False, **kwargs):
- if name != self._target:
- return self._opener(name, mode, **kwargs)
- assert not kwargs
- return randomaccessfile.appender(self._opener, name, mode, self._buf)
-
- def __getattr__(self, attr):
- return getattr(self._opener, attr)
-
-
@attr.s
class _changelogrevision:
# Extensions might modify _defaultextra, so let the constructor below pass
@@ -354,10 +321,7 @@
# chains.
self._storedeltachains = False
- self._realopener = opener
- self._delayed = False
- self._delaybuf = None
- self._divert = False
+ self._v2_delayed = False
self._filteredrevs = frozenset()
self._filteredrevs_hashcache = {}
self._copiesstorage = opener.options.get(b'copies-storage')
@@ -374,90 +338,47 @@
self._filteredrevs_hashcache = {}
def _write_docket(self, tr):
- if not self.is_delaying:
+ if not self._v2_delayed:
super(changelog, self)._write_docket(tr)
- @property
- def is_delaying(self):
- return self._delayed
-
def delayupdate(self, tr):
"""delay visibility of index updates to other readers"""
assert not self._inner.is_open
- if self._docket is None and not self.is_delaying:
- if len(self) == 0:
- self._divert = True
- if self._realopener.exists(self._indexfile + b'.a'):
- self._realopener.unlink(self._indexfile + b'.a')
- self.opener = _divertopener(self._realopener, self._indexfile)
- else:
- self._delaybuf = []
- self.opener = _delayopener(
- self._realopener, self._indexfile, self._delaybuf
- )
- self._inner.opener = self.opener
- self._inner._segmentfile.opener = self.opener
- self._inner._segmentfile_sidedata.opener = self.opener
- self._delayed = True
+ if self._docket is not None:
+ self._v2_delayed = True
+ else:
+ new_index = self._inner.delay()
+ if new_index is not None:
+ self._indexfile = new_index
+ tr.registertmp(new_index)
tr.addpending(b'cl-%i' % id(self), self._writepending)
tr.addfinalize(b'cl-%i' % id(self), self._finalize)
def _finalize(self, tr):
"""finalize index updates"""
assert not self._inner.is_open
- self._delayed = False
- self.opener = self._realopener
- self._inner.opener = self.opener
- self._inner._segmentfile.opener = self.opener
- self._inner._segmentfile_sidedata.opener = self.opener
- # move redirected index data back into place
if self._docket is not None:
- self._write_docket(tr)
- elif self._divert:
- assert not self._delaybuf
- tmpname = self._indexfile + b".a"
- nfile = self.opener.open(tmpname)
- nfile.close()
- self.opener.rename(tmpname, self._indexfile, checkambig=True)
- elif self._delaybuf:
- fp = self.opener(self._indexfile, b'a', checkambig=True)
- fp.write(b"".join(self._delaybuf))
- fp.close()
- self._delaybuf = None
- self._divert = False
- # split when we're done
- self._enforceinlinesize(tr, side_write=False)
+ self._docket.write(tr)
+ self._v2_delayed = False
+ else:
+ new_index_file = self._inner.finalize_pending()
+ self._indexfile = new_index_file
+ # split when we're done
+ self._enforceinlinesize(tr, side_write=False)
def _writepending(self, tr):
"""create a file containing the unfinalized state for
pretxnchangegroup"""
assert not self._inner.is_open
if self._docket:
- return self._docket.write(tr, pending=True)
- if self._delaybuf:
- # make a temporary copy of the index
- fp1 = self._realopener(self._indexfile)
- pendingfilename = self._indexfile + b".a"
- # register as a temp file to ensure cleanup on failure
- tr.registertmp(pendingfilename)
- # write existing data
- fp2 = self._realopener(pendingfilename, b"w")
- fp2.write(fp1.read())
- # add pending data
- fp2.write(b"".join(self._delaybuf))
- fp2.close()
- # switch modes so finalize can simply rename
- self._delaybuf = None
- self._divert = True
- self.opener = _divertopener(self._realopener, self._indexfile)
- self._inner.opener = self.opener
- self._inner._segmentfile.opener = self.opener
- self._inner._segmentfile_sidedata.opener = self.opener
-
- if self._divert:
- return True
-
- return False
+ any_pending = self._docket.write(tr, pending=True)
+ self._v2_delayed = False
+ else:
+ new_index, any_pending = self._inner.write_pending()
+ if new_index is not None:
+ self._indexfile = new_index
+ tr.registertmp(new_index)
+ return any_pending
def _enforceinlinesize(self, tr, side_write=True):
if not self.is_delaying: