[PATCH] hglib: call initialization.init() before loading extensions (for hg >= 7.2)

14 views
Skip to first unread message

Antonio Muci

unread,
Sep 10, 2026, 5:25:19 PM (11 days ago) Sep 10
to thg...@googlegroups.com, a....@inwind.it
# HG changeset patch
# User Antonio Muci <a....@inwind.it>
# Date 1789043188 -7200
# Thu Sep 10 14:26:28 2026 +0200
# Branch stable
# Node ID c847d786cd71efba426566175743dafe09f6a404
# Parent ff01aa72ea781c0dc689a9fa82931b15afccedb8
hglib: call initialization.init() before loading extensions (for hg >= 7.2)

From https://foss.heptapod.net/mercurial/tortoisehg/thg/-/work_items/6045#note_518948
I can confirm that mercurial.initialization.init() need to be called before
extensions are imported (and before we do anything with Mercurial mostly).

That call need to be inserted as soon as possible in the thg bootstrap.

In a first version of this patch, I had modified the thg script and then
run.run(). However, following the call sites, I believe that operating on
hglib.loadextensions() attains the same result and is closer to every actual hg
invocation.

Before this patch, for example, enabling the largefile extension on hg >= 7.2
would cause a crash on thg startup.

Fixes #6045.

diff --git a/tortoisehg/util/hglib.py b/tortoisehg/util/hglib.py
--- a/tortoisehg/util/hglib.py
+++ b/tortoisehg/util/hglib.py
@@ -15,6 +15,7 @@ import re
import shlex
import sys
import time
+import types
import typing

from typing import (
@@ -88,6 +89,18 @@ except ModuleNotFoundError:
from mercurial.dispatch import request
from mercurial.dispatch import _parseconfig as parse_config_opts
from mercurial.dispatch import _earlyparseopts as early_parse_opts
+
+try:
+ # mercurial >= 7.2
+ import mercurial.initialization as initializationmod
+except ModuleNotFoundError:
+ # module mercurial.initialization did not exist in mercurial < 7.2.
+ #
+ # Instead of having to check at runtime if initializationmod is None, let's
+ # build a fake module for this case. In this way, we can simply delete this
+ # code path when we'll need to remove support for mercurial < 7.2.
+ initializationmod = types.ModuleType("initializationmod", "A fake mercurial.initialization module for hg < 7.2")
+ initializationmod.init = lambda: None
# pytype: enable=import-error

if typing.TYPE_CHECKING:
@@ -510,6 +523,12 @@ def _wrapextensionsloader():
def loadextensions(ui: uimod.ui) -> None:
"""Load and setup extensions for GUI process"""
_wrapextensionsloader() # enable blacklist of extensions
+ # https://foss.heptapod.net/mercurial/tortoisehg/thg/-/work_items/6045#note_518948
+ #
+ # Since mercurial >= 7.2, we need to call mercurial.initialization.init()
+ # before interacting with extensions (and before we do anything with
+ # Mercurial mostly).
+ initializationmod.init()
extensions.loadall(ui)


Yuya Nishihara

unread,
Sep 12, 2026, 5:22:23 AM (10 days ago) Sep 12
to 'Antonio Muci' via TortoiseHg Developers, a....@inwind.it
Can you set this to None and test `if initializationmod`? I don't think a fake
module is necessary to just host one dummy function.

Antonio Muci

unread,
Sep 12, 2026, 9:57:59 AM (9 days ago) Sep 12
to thg...@googlegroups.com, a....@inwind.it
# HG changeset patch
# User Antonio Muci <a....@inwind.it>
# Date 1789221296 -7200
# Sat Sep 12 15:54:56 2026 +0200
# Branch stable
# Node ID eac56102c4f9d3e811eb58a1ae43458ddf39d652
# Parent ff01aa72ea781c0dc689a9fa82931b15afccedb8
hglib: call initialization.init() before loading extensions (for hg >= 7.2)

From https://foss.heptapod.net/mercurial/tortoisehg/thg/-/work_items/6045#note_518948
I can confirm that mercurial.initialization.init() need to be called before
extensions are imported (and before we do anything with Mercurial mostly).

That call need to be inserted as soon as possible in the thg bootstrap.

In a first version of this patch, I had modified the thg script and then
run.run(). However, following the call sites, I believe that operating on
hglib.loadextensions() attains the same result and is closer to every actual hg
invocation.

Before this patch, for example, enabling the largefile extension on hg >= 7.2
would cause a crash on thg startup.

Fixes #6045.

diff --git a/tortoisehg/util/hglib.py b/tortoisehg/util/hglib.py
--- a/tortoisehg/util/hglib.py
+++ b/tortoisehg/util/hglib.py
@@ -88,6 +88,14 @@ except ModuleNotFoundError:
from mercurial.dispatch import request
from mercurial.dispatch import _parseconfig as parse_config_opts
from mercurial.dispatch import _earlyparseopts as early_parse_opts
+
+try:
+ # mercurial >= 7.2
+ import mercurial.initialization as initializationmod
+except ModuleNotFoundError:
+ # module mercurial.initialization did not exist in mercurial < 7.2. Before
+ # using initializationmod, we will have to ensure it is not None.
+ pass
# pytype: enable=import-error

if typing.TYPE_CHECKING:
@@ -510,6 +518,13 @@ def _wrapextensionsloader():
def loadextensions(ui: uimod.ui) -> None:
"""Load and setup extensions for GUI process"""
_wrapextensionsloader() # enable blacklist of extensions
+ if initializationmod is not None:
+ # mercurial.initialization.init() before interacting with extensions
+ # (and before we do anything with Mercurial mostly).
+ initializationmod.init()
extensions.loadall(ui)


Yuya Nishihara

unread,
Sep 13, 2026, 6:37:56 AM (9 days ago) Sep 13
to 'Antonio Muci' via TortoiseHg Developers, a....@inwind.it
initializationmod = None

and remove verbose comment: "Before using initializationmod, ..."

If initializationmod isn't excluded from demandimport, it's probably safer to
call .init() within the try-except block.
Reply all
Reply to author
Forward
0 new messages