Skip to content

Commit f040950

Browse files
committed
[IMP] modules: skip autoinstall of unintalled modules
In the case where an autoninstall module is uninstalled by users prior to the upgrade start, this module could be reinstalled during the upgrade if there were dependency changes and those dependencies get force installed. This improvement keeps track of any module that was elligible for autoinstall before the upgrade starts and skips its force installation when dependencies change.
1 parent 3fcc237 commit f040950

File tree

3 files changed

+62
-19
lines changed

3 files changed

+62
-19
lines changed

src/base/0.0.0/pre-00-upgrade-start.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
# -*- coding: utf-8 -*-
1+
from odoo.addons.base.maintenance.migrations import util
2+
from odoo.addons.base.maintenance.migrations.util.modules import _get_autoinstallable_modules
23

34

45
def migrate(cr, version):
@@ -13,3 +14,4 @@ def migrate(cr, version):
1314
WHERE EXCLUDED.value::timestamp - ir_config_parameter.value::timestamp > interval '72 hours'
1415
"""
1516
)
17+
util.ENVIRON["__modules_to_skip_autoinstall"] = _get_autoinstallable_modules(cr)

src/util/const.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"__renamed_fields": collections.defaultdict(dict),
1414
"__modules_auto_discovery_force_installs": {},
1515
"__modules_auto_discovery_force_upgrades": {},
16+
"__modules_to_skip_autoinstall": set(),
1617
"__fix_fk_allowed_cascade": [],
1718
"__no_model_data_delete": {},
1819
}

src/util/modules.py

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ def remove_module(cr, module):
342342

343343
ENVIRON["__modules_auto_discovery_force_installs"].pop(module, None)
344344
ENVIRON["__modules_auto_discovery_force_upgrades"].pop(module, None)
345+
ENVIRON["__modules_to_skip_autoinstall"].discard(module)
345346

346347

347348
def remove_theme(cr, theme, base_theme=None):
@@ -362,6 +363,7 @@ def remove_theme(cr, theme, base_theme=None):
362363

363364
ENVIRON["__modules_auto_discovery_force_installs"].pop(theme, None)
364365
ENVIRON["__modules_auto_discovery_force_upgrades"].pop(theme, None)
366+
ENVIRON["__modules_to_skip_autoinstall"].discard(theme)
365367

366368

367369
def _update_view_key(cr, old, new):
@@ -415,6 +417,10 @@ def rename_module(cr, old, new):
415417
fu = ENVIRON["__modules_auto_discovery_force_upgrades"]
416418
if old in fu:
417419
fu[new] = fu.pop(old)
420+
si = ENVIRON["__modules_to_skip_autoinstall"]
421+
if old in si:
422+
si.discard(old)
423+
si.add(new)
418424

419425

420426
@_warn_usage_outside_base
@@ -450,6 +456,10 @@ def merge_module(cr, old, into, update_dependers=True):
450456
version = fu[old][1] if parse_version(fu[old][1]) < parse_version(fu[into][1]) else fu[into][1]
451457
del fu[old]
452458
fu[into] = (init, version)
459+
si = ENVIRON["__modules_to_skip_autoinstall"]
460+
if old not in si and into in si:
461+
si.discard(into)
462+
si.discard(old)
453463

454464
if old not in mod_ids:
455465
# this can happen in case of temp modules added after a release if the database does not
@@ -721,14 +731,24 @@ def _force_install_module(cr, module, if_installed=None, reason="it has been exp
721731
[toinstall, list(INSTALLED_MODULE_STATES)],
722732
)
723733
for (mod,) in cr.fetchall():
724-
_force_install_module(
725-
cr,
726-
mod,
727-
reason=(
728-
"it is an auto install module that got all its auto install dependencies installed "
729-
"by the force install of {!r}"
730-
).format(module),
731-
)
734+
if mod in ENVIRON["__modules_to_skip_autoinstall"]:
735+
_logger.info(
736+
(
737+
"Module %r won't be auto installed because its original dependencies were already installed. "
738+
"Yet all its auto install dependencies became installed by the force install of %r."
739+
),
740+
mod,
741+
module,
742+
)
743+
else:
744+
_force_install_module(
745+
cr,
746+
mod,
747+
reason=(
748+
"it is an auto install module that got all its auto install dependencies installed "
749+
"by the force install of {!r}"
750+
).format(module),
751+
)
732752

733753
# TODO handle module exclusions
734754

@@ -828,8 +848,19 @@ def module_auto_install(cr, module, auto_install):
828848
@_warn_usage_outside_base
829849
def trigger_auto_install(cr, module):
830850
_assert_modules_exists(cr, module)
851+
to_autoinstall = _get_autoinstallable_modules(cr, module)
852+
if to_autoinstall:
853+
if module in ENVIRON["__modules_to_skip_autoinstall"]:
854+
_logger.info("Skipping the auto installation of module %r because it was previously uninstalled.", module)
855+
return False
856+
force_install_module(cr, module, reason="it's an auto install module and all its dependencies are installed")
857+
return True
858+
return False
859+
860+
861+
def _get_autoinstallable_modules(cr, module=None):
831862
if AUTO_INSTALL == "none":
832-
return False
863+
return set()
833864

834865
dep_match = "true"
835866
if column_exists(cr, "ir_module_module_dependency", "auto_install_required"):
@@ -863,27 +894,36 @@ def trigger_auto_install(cr, module):
863894
hidden = ref(cr, "base.module_category_hidden")
864895
cat_match = cr.mogrify("m.category_id = %s", [hidden]).decode()
865896

866-
query = """
867-
SELECT m.id
897+
name_match = "true"
898+
if module:
899+
name_match = cr.mogrify("m.name = %s", [module]).decode()
900+
901+
query = format_query(
902+
cr,
903+
"""
904+
SELECT m.name
868905
FROM ir_module_module_dependency d
869906
JOIN ir_module_module m ON m.id = d.module_id
870907
JOIN ir_module_module md ON md.name = d.name
871908
{}
872-
WHERE m.name = %s
909+
WHERE {}
873910
AND m.state = 'uninstalled'
874911
AND m.auto_install = true
875912
AND {}
876913
AND {}
877914
GROUP BY m.id
878915
HAVING bool_and(md.state IN %s)
879916
{}
880-
""".format(country_join, dep_match, cat_match, country_match)
917+
""",
918+
SQLStr(country_join),
919+
SQLStr(name_match),
920+
SQLStr(dep_match),
921+
SQLStr(cat_match),
922+
SQLStr(country_match),
923+
)
881924

882-
cr.execute(query, [module, INSTALLED_MODULE_STATES])
883-
if cr.rowcount:
884-
force_install_module(cr, module, reason="it's an auto install module and all its dependencies are installed")
885-
return True
886-
return False
925+
cr.execute(query, [INSTALLED_MODULE_STATES])
926+
return {m[0] for m in cr.fetchall()}
887927

888928

889929
def _set_module_category(cr, module, category):

0 commit comments

Comments
 (0)