Skip to content

Commit 109e00c

Browse files
aj-fuentesKangOl
authored andcommitted
[IMP] core: allow running upgrade scripts unconditionally
Upgrade scripts are run only when there is an update of the module version. This is not flexible enough. After a major upgrade developers need to upgrade their custom modules. Unfortunately the tools in `upgrade-util` repo that modify modules (`merge_module`, `rename_module`, ...) should be done before loading base module. The latter is already upgraded after a major upgrade thus no upgrade scripts are run for it. In this patch we add a mechanism to run specific upgrade scripts before loading base. closes odoo#202014 Related: odoo/documentation#12528 Signed-off-by: Christophe Simonis (chs) <[email protected]> Co-authored-by: Christophe Simonis <[email protected]>
1 parent 0cd5231 commit 109e00c

File tree

4 files changed

+49
-24
lines changed

4 files changed

+49
-24
lines changed

odoo/cli/server.py

+2
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ def report_configuration():
6262
_logger.info('addons paths: %s', odoo.addons.__path__)
6363
if config.get('upgrade_path'):
6464
_logger.info('upgrade path: %s', config['upgrade_path'])
65+
if config.get('pre_upgrade_scripts'):
66+
_logger.info('extra upgrade scripts: %s', config['pre_upgrade_scripts'])
6567
host = config['db_host'] or os.environ.get('PGHOST', 'default')
6668
port = config['db_port'] or os.environ.get('PGPORT', 'default')
6769
user = config['db_user'] or os.environ.get('PGUSER', 'default')

odoo/modules/loading.py

+3
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,9 @@ def load_modules(registry, force_demo=False, status=None, update_module=False):
419419
if not graph:
420420
_logger.critical('module base cannot be loaded! (hint: verify addons-path)')
421421
raise ImportError('Module `base` cannot be loaded! (hint: verify addons-path)')
422+
if update_module and tools.config['update']:
423+
for pyfile in tools.config['pre_upgrade_scripts'].split(','):
424+
odoo.modules.migration.exec_script(cr, graph['base'].installed_version, pyfile, 'base', 'pre')
422425

423426
if update_module and odoo.tools.table_exists(cr, 'ir_model_fields'):
424427
# determine the fields which are currently translated in the database

odoo/modules/migration.py

+22-23
Original file line numberDiff line numberDiff line change
@@ -166,27 +166,26 @@ def compare(version):
166166
versions = _get_migration_versions(pkg, stage)
167167
for version in versions:
168168
if compare(version):
169-
strfmt = {'addon': pkg.name,
170-
'stage': stage,
171-
'version': stageformat[stage] % version,
172-
}
173-
174169
for pyfile in _get_migration_files(pkg, version, stage):
175-
name, ext = os.path.splitext(os.path.basename(pyfile))
176-
if ext.lower() != '.py':
177-
continue
178-
mod = None
179-
try:
180-
mod = load_script(pyfile, name)
181-
_logger.info('module %(addon)s: Running migration %(version)s %(name)s' % dict(strfmt, name=mod.__name__))
182-
migrate = mod.migrate
183-
except ImportError:
184-
_logger.exception('module %(addon)s: Unable to load %(stage)s-migration file %(file)s' % dict(strfmt, file=pyfile))
185-
raise
186-
except AttributeError:
187-
_logger.error('module %(addon)s: Each %(stage)s-migration file must have a "migrate(cr, installed_version)" function' % strfmt)
188-
else:
189-
migrate(self.cr, installed_version)
190-
finally:
191-
if mod:
192-
del mod
170+
exec_script(self.cr, installed_version, pyfile, pkg.name, stage, stageformat[stage] % version)
171+
172+
def exec_script(cr, installed_version, pyfile, addon, stage, version=None):
173+
version = version or installed_version
174+
name, ext = os.path.splitext(os.path.basename(pyfile))
175+
if ext.lower() != '.py':
176+
return
177+
mod = None
178+
try:
179+
mod = load_script(pyfile, name)
180+
_logger.info('module %(addon)s: Running migration %(version)s %(name)s' % dict(locals(), name=mod.__name__))
181+
migrate = mod.migrate
182+
except ImportError:
183+
_logger.exception('module %(addon)s: Unable to load %(stage)s-migration file %(file)s' % dict(locals(), file=pyfile))
184+
raise
185+
except AttributeError:
186+
_logger.error('module %(addon)s: Each %(stage)s-migration file must have a "migrate(cr, installed_version)" function' % locals())
187+
else:
188+
migrate(cr, installed_version)
189+
finally:
190+
if mod:
191+
del mod

odoo/tools/config.py

+22-1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ def __init__(self, fname=None):
124124
group.add_option("--upgrade-path", dest="upgrade_path",
125125
help="specify an additional upgrade path.",
126126
action="callback", callback=self._check_upgrade_path, nargs=1, type="string")
127+
group.add_option("--pre-upgrade-scripts", dest="pre_upgrade_scripts", my_default="",
128+
help="Run specific upgrade scripts before loading any module when -u is provided.",
129+
action="callback", callback=self._check_scripts, nargs=1, type="string")
127130
group.add_option("--load", dest="server_wide_modules", help="Comma-separated list of server-wide modules.", my_default='base,web')
128131

129132
group.add_option("-D", "--data-dir", dest="data_dir", my_default=_get_default_datadir(),
@@ -461,7 +464,7 @@ def die(cond, msg):
461464
'db_port', 'db_template', 'logfile', 'pidfile', 'smtp_port',
462465
'email_from', 'smtp_server', 'smtp_user', 'smtp_password', 'from_filter',
463466
'smtp_ssl_certificate_filename', 'smtp_ssl_private_key_filename',
464-
'db_maxconn', 'import_partial', 'addons_path', 'upgrade_path',
467+
'db_maxconn', 'import_partial', 'addons_path', 'upgrade_path', 'pre_upgrade_scripts',
465468
'syslog', 'without_demo', 'screencasts', 'screenshots',
466469
'dbfilter', 'log_level', 'log_db',
467470
'log_db_level', 'geoip_database', 'dev_mode', 'shell_interface',
@@ -533,6 +536,12 @@ def die(cond, msg):
533536
if self.options['upgrade_path']
534537
else ""
535538
)
539+
self.options["pre_upgrade_scripts"] = (
540+
",".join(self._normalize(x)
541+
for x in self.options['pre_upgrade_scripts'].split(','))
542+
if self.options['pre_upgrade_scripts']
543+
else ""
544+
)
536545

537546
self.options['init'] = opt.init and dict.fromkeys(opt.init.split(','), 1) or {}
538547
self.options['demo'] = (dict(self.options['init'])
@@ -601,6 +610,18 @@ def _check_addons_path(self, option, opt, value, parser):
601610

602611
setattr(parser.values, option.dest, ",".join(ad_paths))
603612

613+
def _check_scripts(self, option, opt, value, parser):
614+
pre_upgrade_scripts = []
615+
for path in value.split(','):
616+
path = path.strip()
617+
res = self._normalize(path)
618+
if not os.path.isfile(res):
619+
raise optparse.OptionValueError("option %s: no such file: %r" % (opt, path))
620+
if res not in pre_upgrade_scripts:
621+
pre_upgrade_scripts.append(res)
622+
setattr(parser.values, option.dest, ",".join(pre_upgrade_scripts))
623+
624+
604625
def _check_upgrade_path(self, option, opt, value, parser):
605626
upgrade_path = []
606627
for path in value.split(','):

0 commit comments

Comments
 (0)