Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/base/0.0.0/pre-00-upgrade-start.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from odoo.addons.base.maintenance.migrations import util
from odoo.addons.base.maintenance.migrations.util.modules import _get_autoinstallable_modules


def migrate(cr, version):
Expand All @@ -13,3 +14,4 @@ def migrate(cr, version):
WHERE EXCLUDED.value::timestamp - ir_config_parameter.value::timestamp > interval '72 hours'
"""
)
util.ENVIRON["__modules_to_skip_autoinstall"] = _get_autoinstallable_modules(cr)
1 change: 1 addition & 0 deletions src/util/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"__renamed_fields": collections.defaultdict(dict),
"__modules_auto_discovery_force_installs": {},
"__modules_auto_discovery_force_upgrades": {},
"__modules_to_skip_autoinstall": set(),
"__fix_fk_allowed_cascade": [],
"__no_model_data_delete": {},
}
Expand Down
76 changes: 58 additions & 18 deletions src/util/modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ def remove_module(cr, module):

ENVIRON["__modules_auto_discovery_force_installs"].pop(module, None)
ENVIRON["__modules_auto_discovery_force_upgrades"].pop(module, None)
ENVIRON["__modules_to_skip_autoinstall"].discard(module)


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

ENVIRON["__modules_auto_discovery_force_installs"].pop(theme, None)
ENVIRON["__modules_auto_discovery_force_upgrades"].pop(theme, None)
ENVIRON["__modules_to_skip_autoinstall"].discard(theme)


def _update_view_key(cr, old, new):
Expand Down Expand Up @@ -415,6 +417,10 @@ def rename_module(cr, old, new):
fu = ENVIRON["__modules_auto_discovery_force_upgrades"]
if old in fu:
fu[new] = fu.pop(old)
si = ENVIRON["__modules_to_skip_autoinstall"]
if old in si:
si.discard(old)
si.add(new)


@_warn_usage_outside_base
Expand Down Expand Up @@ -450,6 +456,10 @@ def merge_module(cr, old, into, update_dependers=True):
version = fu[old][1] if parse_version(fu[old][1]) < parse_version(fu[into][1]) else fu[into][1]
del fu[old]
fu[into] = (init, version)
si = ENVIRON["__modules_to_skip_autoinstall"]
if old not in si and into in si:
si.discard(into)
si.discard(old)

if old not in mod_ids:
# this can happen in case of temp modules added after a release if the database does not
Expand Down Expand Up @@ -721,14 +731,24 @@ def _force_install_module(cr, module, if_installed=None, reason="it has been exp
[toinstall, list(INSTALLED_MODULE_STATES)],
)
for (mod,) in cr.fetchall():
_force_install_module(
cr,
mod,
reason=(
"it is an auto install module that got all its auto install dependencies installed "
"by the force install of {!r}"
).format(module),
)
if mod in ENVIRON["__modules_to_skip_autoinstall"]:
_logger.info(
(
"Module %r won't be auto installed because its original dependencies were already installed. "
"Yet all its auto install dependencies became installed by the force install of %r."
),
mod,
module,
)
else:
_force_install_module(
cr,
mod,
reason=(
"it is an auto install module that got all its auto install dependencies installed "
"by the force install of {!r}"
).format(module),
)

# TODO handle module exclusions

Expand Down Expand Up @@ -828,8 +848,19 @@ def module_auto_install(cr, module, auto_install):
@_warn_usage_outside_base
def trigger_auto_install(cr, module):
_assert_modules_exists(cr, module)
to_autoinstall = _get_autoinstallable_modules(cr, module)
if to_autoinstall:
if module in ENVIRON["__modules_to_skip_autoinstall"]:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This at the moment is not doing anything because the method trigger_auto_install is only called in the context of new_module and in some pre scripts also for new modules. But it does not hurt to keep it just in case, as the method can be called elsewhere

_logger.info("Skipping the auto installation of module %r because it was previously uninstalled.", module)
return False
force_install_module(cr, module, reason="it's an auto install module and all its dependencies are installed")
return True
return False


def _get_autoinstallable_modules(cr, module=None):
if AUTO_INSTALL == "none":
return False
return set()

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

query = """
SELECT m.id
name_match = "true"
if module:
name_match = cr.mogrify("m.name = %s", [module]).decode()

query = format_query(
cr,
"""
SELECT m.name
FROM ir_module_module_dependency d
JOIN ir_module_module m ON m.id = d.module_id
JOIN ir_module_module md ON md.name = d.name
{}
WHERE m.name = %s
WHERE {}
AND m.state = 'uninstalled'
AND m.auto_install = true
AND {}
AND {}
GROUP BY m.id
HAVING bool_and(md.state IN %s)
{}
""".format(country_join, dep_match, cat_match, country_match)
""",
SQLStr(country_join),
SQLStr(name_match),
SQLStr(dep_match),
SQLStr(cat_match),
SQLStr(country_match),
)

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


def _set_module_category(cr, module, category):
Expand Down