Mercurial > hg
view mercurial/scmwindows.py @ 51637:3cf9e52f5e27 stable
inline-changelog: fix a critical bug in write_pending that delete data
Since a93e52f0b6ff we no longer use inline-revlog for the changelog. The goal there was to
solve the lack of testing for the two variants (inline vs split) and reduce the
complexity of the interaction with "diverted-write" on the changelog level.
However many existing repository still have inline-changelog and we
automatically move them to normal revlog as soon as we have the chances.
Unfortunately This conversion is buggy and can result in the destruction of the
changelog.i if hook triggers the "write pending" mechanism.
The bugs comes from the "revlog splitting" logic and the "write_pending" logic
stepping over each other. Ironically the change in a93e52f0b6ff aims at no
longer having this kind of problem.
This changesets fix this issue and add associated tests.
Fixing this reveal that the transaction hooks end up not seeing the pending
transaction content, because the name is not right ("changelog.i.s.a" instead of
"changelog.i.s") we fix this in the next changeset.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Wed, 12 Jun 2024 02:15:20 +0200 |
parents | 9d3721552b6c |
children | f4733654f144 |
line wrap: on
line source
import os import winreg # pytype: disable=import-error from typing import ( List, TYPE_CHECKING, Tuple, ) from . import ( encoding, pycompat, util, win32, ) if TYPE_CHECKING: from . import ui as uimod # MS-DOS 'more' is the only pager available by default on Windows. fallbackpager = b'more' def systemrcpath() -> List[bytes]: '''return default os-specific hgrc search path''' rcpath = [] filename = win32.executablepath() # Use mercurial.ini found in directory with hg.exe progrc = os.path.join(os.path.dirname(filename), b'mercurial.ini') rcpath.append(progrc) def _processdir(progrcd: bytes) -> None: if os.path.isdir(progrcd): for f, kind in sorted(util.listdir(progrcd)): if f.endswith(b'.rc'): rcpath.append(os.path.join(progrcd, f)) # Use hgrc.d found in directory with hg.exe _processdir(os.path.join(os.path.dirname(filename), b'hgrc.d')) # treat a PROGRAMDATA directory as equivalent to /etc/mercurial programdata = encoding.environ.get(b'PROGRAMDATA') if programdata: programdata = os.path.join(programdata, b'Mercurial') _processdir(os.path.join(programdata, b'hgrc.d')) ini = os.path.join(programdata, b'mercurial.ini') if os.path.isfile(ini): rcpath.append(ini) ini = os.path.join(programdata, b'hgrc') if os.path.isfile(ini): rcpath.append(ini) # next look for a system rcpath in the registry value = util.lookupreg( # pytype: disable=module-attr b'SOFTWARE\\Mercurial', None, winreg.HKEY_LOCAL_MACHINE # pytype: enable=module-attr ) if value and isinstance(value, bytes): value = util.localpath(value) for p in value.split(pycompat.ospathsep): if p.lower().endswith(b'mercurial.ini'): rcpath.append(p) else: _processdir(p) return rcpath def userrcpath() -> List[bytes]: '''return os-specific hgrc search path to the user dir''' home = _legacy_expanduser(b'~') path = [os.path.join(home, b'mercurial.ini'), os.path.join(home, b'.hgrc')] userprofile = encoding.environ.get(b'USERPROFILE') if userprofile and userprofile != home: path.append(os.path.join(userprofile, b'mercurial.ini')) path.append(os.path.join(userprofile, b'.hgrc')) return path def _legacy_expanduser(path: bytes) -> bytes: """Expand ~ and ~user constructs in the pre 3.8 style""" # Python 3.8+ changed the expansion of '~' from HOME to USERPROFILE. See # https://bugs.python.org/issue36264. It also seems to capitalize the drive # letter, as though it was processed through os.path.realpath(). if not path.startswith(b'~'): return path i, n = 1, len(path) while i < n and path[i] not in b'\\/': i += 1 if b'HOME' in encoding.environ: userhome = encoding.environ[b'HOME'] elif b'USERPROFILE' in encoding.environ: userhome = encoding.environ[b'USERPROFILE'] elif b'HOMEPATH' not in encoding.environ: return path else: try: drive = encoding.environ[b'HOMEDRIVE'] except KeyError: drive = b'' userhome = os.path.join(drive, encoding.environ[b'HOMEPATH']) if i != 1: # ~user userhome = os.path.join(os.path.dirname(userhome), path[1:i]) return userhome + path[i:] def termsize(ui: "uimod.ui") -> Tuple[int, int]: return win32.termsize()