From bbb1a8f151b07d0125fc6d7d89375aa22681aac5 Mon Sep 17 00:00:00 2001 From: Laurent Contzen Date: Thu, 11 Apr 2019 09:48:35 +0000 Subject: [PATCH] [IMP] ORM: Add new --upgrades-paths CLI option This commit adds a new way to use upgrades scripts folders whithout needing to symlink them to an hardcoded path. The folders specified in --upgrades-paths is then being used by migration.py to find and execute migrations scripts per module specified in the -u CLI option. The folder needs to have the following structure: - - - - - - ... - - - - - - - ... - - ... Update odoo/tools/config.py Co-Authored-By: Olivier Dony --- odoo/cli/server.py | 2 ++ odoo/modules/migration.py | 19 ++++++++++++++++++- odoo/tools/config.py | 22 +++++++++++++++++++++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/odoo/cli/server.py b/odoo/cli/server.py index 93f40126839..fcb7f2de700 100644 --- a/odoo/cli/server.py +++ b/odoo/cli/server.py @@ -60,6 +60,8 @@ def report_configuration(): if os.path.isfile(config.rcfile): _logger.info("Using configuration file at " + config.rcfile) _logger.info('addons paths: %s', odoo.modules.module.ad_paths) + if config.get('upgrades_paths'): + _logger.info('upgrades path: %s', config['upgrades_paths']) host = config['db_host'] or os.environ.get('PGHOST', 'default') port = config['db_port'] or os.environ.get('PGPORT', 'default') user = config['db_user'] or os.environ.get('PGUSER', 'default') diff --git a/odoo/modules/migration.py b/odoo/modules/migration.py index 6331af43660..8faf8735a8d 100644 --- a/odoo/modules/migration.py +++ b/odoo/modules/migration.py @@ -19,7 +19,7 @@ _logger = logging.getLogger(__name__) def load_script(path, module_name): - full_path = get_resource_path(*path.split(os.path.sep)) + 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) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) @@ -62,6 +62,13 @@ class MigrationManager(object): self._get_files() def _get_files(self): + def _get_upgrades_paths(pkg): + for path in tools.config['upgrades_paths'].split(','): + upgrade_path = opj(path, pkg) + if os.path.exists(upgrade_path): + return upgrade_path + return None + def get_scripts(path): if not path: return {} @@ -78,7 +85,10 @@ class MigrationManager(object): self.migrations[pkg.name] = { 'module': get_scripts(get_resource_path(pkg.name, 'migrations')), + 'module_upgrades': get_scripts(get_resource_path(pkg.name, 'upgrades')), 'maintenance': get_scripts(get_resource_path('base', 'maintenance', 'migrations', pkg.name)), + 'maintenance_upgrades': get_scripts(get_resource_path('base', 'maintenance', 'upgrades', pkg.name)), + 'upgrades': get_scripts(_get_upgrades_paths(pkg.name)), } def migrate_module(self, pkg, stage): @@ -122,9 +132,16 @@ class MigrationManager(object): mapping = { 'module': opj(pkg.name, 'migrations'), + 'module_upgrades': opj(pkg.name, 'upgrades'), 'maintenance': opj('base', 'maintenance', 'migrations', pkg.name), + 'maintenance_upgrades': opj('base', 'maintenance', 'upgrades', pkg.name), } + for path in tools.config['upgrades_paths'].split(','): + if os.path.exists(opj(path, pkg.name)): + mapping['upgrades'] = opj(path, pkg.name) + break + for x in mapping: if version in m.get(x): for f in m[x][version]: diff --git a/odoo/tools/config.py b/odoo/tools/config.py index ef409de56f9..677628835b4 100644 --- a/odoo/tools/config.py +++ b/odoo/tools/config.py @@ -118,6 +118,9 @@ class configmanager(object): group.add_option("--addons-path", dest="addons_path", help="specify additional addons paths (separated by commas).", action="callback", callback=self._check_addons_path, nargs=1, type="string") + group.add_option("--upgrades-paths", dest="upgrades_paths", + help="specify an additional upgrades path.", + action="callback", callback=self._check_upgrades_paths, nargs=1, type="string") group.add_option("--load", dest="server_wide_modules", help="Comma-separated list of server-wide modules.", my_default='base,web') group.add_option("-D", "--data-dir", dest="data_dir", my_default=_get_default_datadir(), @@ -420,7 +423,7 @@ class configmanager(object): 'db_name', 'db_user', 'db_password', 'db_host', 'db_sslmode', 'db_port', 'db_template', 'logfile', 'pidfile', 'smtp_port', 'email_from', 'smtp_server', 'smtp_user', 'smtp_password', - 'db_maxconn', 'import_partial', 'addons_path', + 'db_maxconn', 'import_partial', 'addons_path', 'upgrades_paths', 'syslog', 'without_demo', 'screencasts', 'screenshots', 'dbfilter', 'log_level', 'log_db', 'log_db_level', 'geoip_database', 'dev_mode', 'shell_interface' @@ -485,6 +488,13 @@ class configmanager(object): os.path.abspath(os.path.expanduser(os.path.expandvars(x.strip()))) for x in self.options['addons_path'].split(',')) + self.options['upgrades_paths'] = ( + ",".join(os.path.abspath(os.path.expanduser(os.path.expandvars(x.strip()))) + for x in self.options['upgrades_paths'].split(',')) + if self.options['upgrades_paths'] + else "" + ) + self.options['data_dir'] = os.path.abspath(os.path.expanduser(os.path.expandvars(self.options['data_dir'].strip()))) self.options['init'] = opt.init and dict.fromkeys(opt.init.split(','), 1) or {} @@ -539,6 +549,16 @@ class configmanager(object): setattr(parser.values, option.dest, ",".join(ad_paths)) + def _check_upgrades_paths(self, option, opt, value, parser): + upgrades_paths = [] + for path in value.split(','): + path = path.strip() + res = os.path.abspath(os.path.expanduser(os.path.expandvars(path))) + if not os.path.isdir(res): + raise optparse.OptionValueError("option %s: no such directory: %r" % (opt, path)) + upgrades_paths.append(res) + setattr(parser.values, option.dest, ",".join(upgrades_paths)) + def _test_enable_callback(self, option, opt, value, parser): if not parser.values.test_tags: parser.values.test_tags = "+standard"