[FIX] core: consider x.y.z upgrade scripts as majorless

Also warn about invalid version numbers in upgrade scripts.

closes odoo/odoo#118420

Related: odoo/enterprise#39698
Related: odoo/upgrade#4554
Signed-off-by: Christophe Simonis <chs@odoo.com>
Co-authored-by: Alvaro Fuentes <afu@odoo.com>
This commit is contained in:
Christophe Simonis
2023-05-02 18:06:44 +02:00
co-authored by Alvaro Fuentes
parent 653ec8cf60
commit 6c2a487ef9
+47 -3
View File
@@ -8,6 +8,7 @@ import glob
import importlib.util
import logging
import os
import re
from os.path import join as opj
from odoo.modules.module import get_resource_path
@@ -18,6 +19,33 @@ from odoo.tools.parse_version import parse_version
_logger = logging.getLogger(__name__)
VERSION_RE = re.compile(
r"""^
# Optional prefix with Odoo version
((
6\.1|
# "x.0" version, with x >= 6.
[6-9]\.0|
# multi digits "x.0" versions
[1-9]\d+\.0|
# x.saas~y, where x >= 7 and x <= 10
(7|8|9|10)\.saas~[1-9]\d*|
# saas~x.y, where x >= 11 and y between 1 and 9
# FIXME handle version >= saas~100 (expected in year 2106)
saas~(1[1-9]|[2-9]\d+)\.[1-9]
)\.)?
# After Odoo version we allow precisely 2 or 3 parts
# note this will also allow 0.0.0 which has a special meaning
\d+\.\d+(\.\d+)?
$""",
re.VERBOSE | re.ASCII,
)
def load_script(path, module_name):
full_path = get_resource_path(*path.split(os.path.sep)) if not os.path.isabs(path) else path
spec = importlib.util.spec_from_file_location(module_name, full_path)
@@ -71,13 +99,27 @@ class MigrationManager(object):
if os.path.exists(upgrade_path):
yield upgrade_path
def _verify_upgrade_version(path, version):
full_path = opj(path, version)
if not os.path.isdir(full_path):
return False
if version == "tests":
return False
if not VERSION_RE.match(version):
_logger.warning("Invalid version for upgrade script %r", full_path)
return False
return True
def get_scripts(path):
if not path:
return {}
return {
version: glob.glob(opj(path, version, '*.py'))
for version in os.listdir(path)
if os.path.isdir(opj(path, version))
if _verify_upgrade_version(path, version)
}
for pkg in self.graph:
@@ -109,8 +151,10 @@ class MigrationManager(object):
return
def convert_version(version):
if version.count('.') >= 2:
return version # the version number already contains the server version
if version == "0.0.0":
return version
if version.count(".") > 2:
return version # the version number already contains the server version, see VERSION_RE for details
return "%s.%s" % (release.major_version, version)
def _get_migration_versions(pkg, stage):