2025-10-31 01:10:54 -04:00
|
|
|
|
#!/usr/bin/env python3
|
2026-03-11 23:15:07 -04:00
|
|
|
|
# © 2021-2026 TechnoLibre (http://www.technolibre.ca)
|
2025-10-31 01:10:54 -04:00
|
|
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
|
|
|
|
|
|
|
|
|
|
|
import datetime
|
|
|
|
|
|
import json
|
|
|
|
|
|
import logging
|
|
|
|
|
|
import os
|
|
|
|
|
|
import shutil
|
|
|
|
|
|
import sys
|
|
|
|
|
|
import zipfile
|
|
|
|
|
|
from uuid import uuid4
|
2026-03-26 15:45:44 -04:00
|
|
|
|
from script.todo.version_manager import get_odoo_version
|
2025-10-31 01:10:54 -04:00
|
|
|
|
|
|
|
|
|
|
import click
|
|
|
|
|
|
import todo_file_browser
|
|
|
|
|
|
|
|
|
|
|
|
new_path = os.path.normpath(
|
|
|
|
|
|
os.path.join(os.path.dirname(__file__), "..", "..")
|
|
|
|
|
|
)
|
|
|
|
|
|
sys.path.append(new_path)
|
|
|
|
|
|
|
2026-02-13 01:27:38 -05:00
|
|
|
|
from script.execute import execute
|
2025-10-31 01:10:54 -04:00
|
|
|
|
from script.git.git_tool import GitTool
|
|
|
|
|
|
|
|
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
PYTHON_BIN = ".venv.erplibre/bin/python3"
|
|
|
|
|
|
UPGRADE_DATABASE_CONFIG_LOG = ".venv.erplibre/odoo_database_migration_log.json"
|
|
|
|
|
|
# UPGRADE_MODULE_CONFIG_LOG = ".venv.erplibre/odoo_module_migration_log.json"
|
|
|
|
|
|
VENV_NAME_MODULE_MIGRATOR = ".venv"
|
|
|
|
|
|
LST_PATH_OCA_ODOO_MODULE_MIGRATOR = ["script", "OCA_odoo-module-migrator"]
|
|
|
|
|
|
PATH_OCA_ODOO_MODULE_MIGRATOR = "./" + "/".join(
|
|
|
|
|
|
LST_PATH_OCA_ODOO_MODULE_MIGRATOR
|
|
|
|
|
|
)
|
|
|
|
|
|
PATH_VENV_MODULE_MIGRATOR = os.path.join(
|
|
|
|
|
|
PATH_OCA_ODOO_MODULE_MIGRATOR, VENV_NAME_MODULE_MIGRATOR
|
|
|
|
|
|
)
|
|
|
|
|
|
PATH_SOURCE_VENV_MODULE_MIGRATOR = os.path.join(
|
|
|
|
|
|
PATH_VENV_MODULE_MIGRATOR, "bin", "activate"
|
|
|
|
|
|
)
|
|
|
|
|
|
FILENAME_ODOO_VERSION = ".odoo-version"
|
|
|
|
|
|
LOCAL_MANIFEST = os.path.join(
|
|
|
|
|
|
".repo", "local_manifests", "erplibre_manifest.xml"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TodoUpgrade:
|
|
|
|
|
|
def __init__(self, todo):
|
|
|
|
|
|
self.file_path = None
|
|
|
|
|
|
self.dir_path = None
|
|
|
|
|
|
self.todo = todo
|
|
|
|
|
|
self.dct_progression = {}
|
|
|
|
|
|
self.lst_command_executed = []
|
|
|
|
|
|
self.dct_module_per_version = {}
|
|
|
|
|
|
self.dct_module_per_dct_version_path = {}
|
2026-02-13 01:27:38 -05:00
|
|
|
|
self.execute = execute.Execute()
|
2025-10-31 01:10:54 -04:00
|
|
|
|
|
|
|
|
|
|
def write_config(self):
|
|
|
|
|
|
if "date_create" not in self.dct_progression.keys():
|
|
|
|
|
|
self.dct_progression["date_create"] = str(datetime.datetime.now())
|
|
|
|
|
|
self.dct_progression["date_update"] = str(datetime.datetime.now())
|
|
|
|
|
|
# Always put command_executed at the end
|
|
|
|
|
|
if "command_executed" in self.dct_progression.keys():
|
|
|
|
|
|
value = self.dct_progression["command_executed"]
|
|
|
|
|
|
del self.dct_progression["command_executed"]
|
|
|
|
|
|
self.dct_progression["command_executed"] = value
|
|
|
|
|
|
with open(UPGRADE_DATABASE_CONFIG_LOG, "w") as f:
|
|
|
|
|
|
json.dump(self.dct_progression, f, indent=4)
|
|
|
|
|
|
|
|
|
|
|
|
def on_file_selected(self, file_path):
|
|
|
|
|
|
self.file_path = file_path
|
|
|
|
|
|
todo_file_browser.exit_program()
|
|
|
|
|
|
|
|
|
|
|
|
def on_dir_selected(self, dir_path):
|
|
|
|
|
|
self.dir_path = dir_path
|
|
|
|
|
|
todo_file_browser.exit_program()
|
|
|
|
|
|
|
|
|
|
|
|
def execute_module_upgrade(self):
|
|
|
|
|
|
print("Welcome to Odoo module upgrade processus with ERPLibre 🤖")
|
|
|
|
|
|
|
2025-11-11 00:05:33 -05:00
|
|
|
|
if os.path.exists(UPGRADE_DATABASE_CONFIG_LOG):
|
|
|
|
|
|
with open(UPGRADE_DATABASE_CONFIG_LOG, "r") as f:
|
|
|
|
|
|
try:
|
|
|
|
|
|
old_dct_progression = json.load(f)
|
|
|
|
|
|
self.dct_progression = old_dct_progression
|
|
|
|
|
|
self.lst_command_executed = old_dct_progression.get(
|
|
|
|
|
|
"command_executed"
|
|
|
|
|
|
)
|
|
|
|
|
|
except json.decoder.JSONDecodeError:
|
|
|
|
|
|
print(
|
|
|
|
|
|
f'⚠️ The config file "{UPGRADE_DATABASE_CONFIG_LOG}" is invalid, ignore it.'
|
|
|
|
|
|
)
|
2025-10-31 01:10:54 -04:00
|
|
|
|
|
|
|
|
|
|
print(
|
|
|
|
|
|
"Migrate a directory repo to migrate all module, or select a directory module."
|
|
|
|
|
|
)
|
|
|
|
|
|
print("[m] Migrate one module")
|
|
|
|
|
|
print("[r] Migrate one repo")
|
|
|
|
|
|
print("[] Directory browser")
|
|
|
|
|
|
|
|
|
|
|
|
lst_dir_path = []
|
|
|
|
|
|
from_version = 0
|
|
|
|
|
|
to_version = 0
|
|
|
|
|
|
|
|
|
|
|
|
status = input("💬 What do you choose : ").strip().lower()
|
|
|
|
|
|
if status == "m":
|
|
|
|
|
|
print("[p] Path (default)")
|
|
|
|
|
|
print("[n] Name")
|
|
|
|
|
|
|
|
|
|
|
|
status = input("💬 What do you choose : ").strip().lower()
|
|
|
|
|
|
if status == "n":
|
|
|
|
|
|
module_name = input("💬 Module name : ").strip().lower()
|
|
|
|
|
|
from_version = int(
|
|
|
|
|
|
input("💬 From odoo version (12 to 18) : ").strip()
|
|
|
|
|
|
)
|
|
|
|
|
|
to_version = int(
|
|
|
|
|
|
input("💬 To odoo version (12 to 18) : ").strip()
|
|
|
|
|
|
)
|
|
|
|
|
|
self.switch_odoo(from_version)
|
|
|
|
|
|
# TODO detect path
|
|
|
|
|
|
(
|
|
|
|
|
|
lst_module_missing,
|
|
|
|
|
|
lst_module_duplicate,
|
|
|
|
|
|
lst_module_exist,
|
|
|
|
|
|
lst_module_error,
|
|
|
|
|
|
) = self.check_addons_exist([module_name], get_all_info=True)
|
|
|
|
|
|
if (
|
|
|
|
|
|
lst_module_missing
|
|
|
|
|
|
or lst_module_duplicate
|
|
|
|
|
|
or lst_module_error
|
|
|
|
|
|
):
|
|
|
|
|
|
if lst_module_missing:
|
|
|
|
|
|
print(f"Missing list : {lst_module_missing}")
|
|
|
|
|
|
if lst_module_duplicate:
|
|
|
|
|
|
print(f"Duplicate list : {lst_module_duplicate}")
|
|
|
|
|
|
if lst_module_error:
|
|
|
|
|
|
print(f"Error list : {lst_module_error}")
|
|
|
|
|
|
return
|
|
|
|
|
|
lst_dir_path.extend(lst_module_exist)
|
|
|
|
|
|
else:
|
|
|
|
|
|
self.dir_path = input("💬 Path : ").strip()
|
|
|
|
|
|
elif status == "r":
|
|
|
|
|
|
self.dir_path = input("💬 Path : ").strip()
|
|
|
|
|
|
else:
|
|
|
|
|
|
self.dir_path = None
|
|
|
|
|
|
|
|
|
|
|
|
if not self.dir_path and not lst_dir_path:
|
|
|
|
|
|
initial_dir = os.getcwd()
|
|
|
|
|
|
|
|
|
|
|
|
file_browser = todo_file_browser.FileBrowser(
|
|
|
|
|
|
initial_dir, self.on_dir_selected, open_dir=True
|
|
|
|
|
|
)
|
|
|
|
|
|
file_browser.run_main_frame()
|
|
|
|
|
|
|
|
|
|
|
|
if not lst_dir_path and not os.path.exists(self.dir_path):
|
|
|
|
|
|
_logger.error(f"Path '{self.dir_path}' not exists.")
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
if not from_version:
|
|
|
|
|
|
from_version = int(
|
|
|
|
|
|
input("💬 From odoo version (12 to 18) : ").strip()
|
|
|
|
|
|
)
|
|
|
|
|
|
if not to_version:
|
|
|
|
|
|
to_version = int(input("💬 To odoo version (12 to 18) : ").strip())
|
|
|
|
|
|
|
|
|
|
|
|
# TODO ask option direct migration
|
|
|
|
|
|
|
|
|
|
|
|
lst_version_to_update = [
|
|
|
|
|
|
(a, a + 1) for a in range(from_version, to_version)
|
|
|
|
|
|
]
|
|
|
|
|
|
# lst_version_to_update = [(from_version, to_version)]
|
|
|
|
|
|
# for actual_version in range(from_version, to_version):
|
|
|
|
|
|
# next_version = actual_version + 1
|
|
|
|
|
|
for actual_version, next_version in lst_version_to_update:
|
|
|
|
|
|
set_path_migrate_addons = set()
|
|
|
|
|
|
|
|
|
|
|
|
if not lst_dir_path:
|
|
|
|
|
|
if os.path.exists(
|
|
|
|
|
|
os.path.join(self.dir_path, "__manifest__.py")
|
|
|
|
|
|
):
|
|
|
|
|
|
lst_dir_path = [
|
|
|
|
|
|
[os.path.basename(self.dir_path), self.dir_path]
|
|
|
|
|
|
]
|
|
|
|
|
|
else:
|
|
|
|
|
|
lst_dir_path = [
|
|
|
|
|
|
[a, os.path.join(self.dir_path, a)]
|
|
|
|
|
|
for a in os.listdir(self.dir_path)
|
|
|
|
|
|
if os.path.exists(
|
|
|
|
|
|
os.path.join(self.dir_path, a, "__manifest__.py")
|
|
|
|
|
|
)
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
lst_path_git_clone_migrate = []
|
|
|
|
|
|
lst_module_to_migrate_all = []
|
|
|
|
|
|
for dir_path in lst_dir_path:
|
|
|
|
|
|
source_manifest_path = os.path.join(
|
|
|
|
|
|
dir_path[1], "__manifest__.py"
|
|
|
|
|
|
).replace(f"odoo{from_version}.0", f"odoo{actual_version}.0")
|
|
|
|
|
|
|
|
|
|
|
|
is_dir_module = os.path.exists(source_manifest_path)
|
|
|
|
|
|
if not is_dir_module:
|
|
|
|
|
|
continue
|
|
|
|
|
|
source_module_path = dir_path[1].replace(
|
|
|
|
|
|
f"odoo{from_version}.0", f"odoo{actual_version}.0"
|
|
|
|
|
|
)
|
|
|
|
|
|
source_addons_path = os.path.dirname(dir_path[1]).replace(
|
|
|
|
|
|
f"odoo{from_version}.0", f"odoo{actual_version}.0"
|
|
|
|
|
|
)
|
|
|
|
|
|
target_module_path = source_module_path.replace(
|
|
|
|
|
|
f"odoo{actual_version}.0", f"odoo{next_version}.0"
|
|
|
|
|
|
)
|
|
|
|
|
|
target_manifest_path = source_manifest_path.replace(
|
|
|
|
|
|
f"odoo{actual_version}.0", f"odoo{next_version}.0"
|
|
|
|
|
|
)
|
|
|
|
|
|
target_addons_path = source_addons_path.replace(
|
|
|
|
|
|
f"odoo{actual_version}.0", f"odoo{next_version}.0"
|
|
|
|
|
|
)
|
|
|
|
|
|
dct_module = {
|
|
|
|
|
|
"source_module_path": source_module_path,
|
|
|
|
|
|
"source_manifest_path": source_manifest_path,
|
|
|
|
|
|
"source_addons_path": source_addons_path,
|
|
|
|
|
|
"target_module_path": target_module_path,
|
|
|
|
|
|
"target_manifest_path": target_manifest_path,
|
|
|
|
|
|
"target_addons_path": target_addons_path,
|
|
|
|
|
|
"module_name": dir_path[0],
|
|
|
|
|
|
"source_version_odoo": actual_version,
|
|
|
|
|
|
"target_version_odoo": next_version,
|
|
|
|
|
|
}
|
|
|
|
|
|
lst_module_to_migrate_all.append(dct_module)
|
|
|
|
|
|
set_path_migrate_addons.add(target_addons_path)
|
|
|
|
|
|
# lst_path_git_clone_migrate.append(target_addons_path)
|
|
|
|
|
|
# TODO auto detect version from
|
|
|
|
|
|
# TODO if detect from directory, check from repo list
|
|
|
|
|
|
# TODO detect from manifest version
|
|
|
|
|
|
|
|
|
|
|
|
self.switch_odoo(next_version)
|
|
|
|
|
|
self.install_OCA_odoo_module_migrator()
|
|
|
|
|
|
|
|
|
|
|
|
self.internal_module_upgrade(
|
|
|
|
|
|
next_version,
|
|
|
|
|
|
lst_module_to_migrate_all,
|
|
|
|
|
|
lst_path_git_clone_migrate,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
for commit_path in set_path_migrate_addons:
|
|
|
|
|
|
cmd = f"./script/code/git_commit_migration_addons_path.py --path {commit_path} --odoo_version {next_version}.0"
|
|
|
|
|
|
self.todo_upgrade_execute(cmd)
|
|
|
|
|
|
print(set_path_migrate_addons)
|
|
|
|
|
|
status = input(
|
|
|
|
|
|
f"💬 Please validate git commit on repos, press to continue : "
|
|
|
|
|
|
).strip()
|
|
|
|
|
|
|
|
|
|
|
|
def internal_module_upgrade(
|
|
|
|
|
|
self,
|
|
|
|
|
|
next_version,
|
|
|
|
|
|
lst_module_to_migrate_all,
|
|
|
|
|
|
lst_path_git_clone_migrate,
|
|
|
|
|
|
):
|
|
|
|
|
|
has_cmd = False
|
|
|
|
|
|
cmd_parallel = "parallel :::"
|
|
|
|
|
|
for dct_module in lst_module_to_migrate_all:
|
|
|
|
|
|
target_addons_path = dct_module.get("target_addons_path")
|
|
|
|
|
|
source_addons_path = dct_module.get("source_addons_path")
|
|
|
|
|
|
module_name = dct_module.get("module_name")
|
|
|
|
|
|
source_version_odoo = f'{dct_module.get("source_version_odoo")}.0'
|
|
|
|
|
|
target_version_odoo = f'{dct_module.get("target_version_odoo")}.0'
|
|
|
|
|
|
source_module_path_to_copy = dct_module.get("source_module_path")
|
|
|
|
|
|
# Prepare git environment for target
|
|
|
|
|
|
if target_addons_path not in lst_path_git_clone_migrate:
|
|
|
|
|
|
lst_path_git_clone_migrate.append(target_addons_path)
|
|
|
|
|
|
self.check_and_clone_source_to_target_migration_code(
|
|
|
|
|
|
next_version,
|
|
|
|
|
|
source_addons_path,
|
|
|
|
|
|
target_addons_path,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
cmd_migration = (
|
|
|
|
|
|
f"echo 'odoo_module_migrate {module_name}' && "
|
|
|
|
|
|
f"cp -r {source_module_path_to_copy} {target_addons_path} && "
|
|
|
|
|
|
f"cd {PATH_OCA_ODOO_MODULE_MIGRATOR} && "
|
|
|
|
|
|
f"source {VENV_NAME_MODULE_MIGRATOR}/bin/activate && "
|
|
|
|
|
|
f"python -m odoo_module_migrate --directory {target_addons_path} --modules {module_name} "
|
|
|
|
|
|
f"--init-version-name {source_version_odoo} --target-version-name {target_version_odoo} "
|
|
|
|
|
|
f"--no-commit && "
|
|
|
|
|
|
f"cd ~- "
|
|
|
|
|
|
# f"cp -r {source_module_path_to_copy} {target_module_path_to_copy} && "
|
|
|
|
|
|
# f"cd {target_module_path_to_copy} && git commit -am '[MIG] {module_name}: Migration to {target_version_odoo}' && cd ~-"
|
|
|
|
|
|
)
|
|
|
|
|
|
cmd_parallel += f' "{cmd_migration}"'
|
|
|
|
|
|
has_cmd = True
|
|
|
|
|
|
|
|
|
|
|
|
if lst_module_to_migrate_all:
|
|
|
|
|
|
if has_cmd:
|
|
|
|
|
|
self.todo_upgrade_execute(cmd_parallel)
|
|
|
|
|
|
print("List of path with migrate code :")
|
|
|
|
|
|
print(lst_path_git_clone_migrate)
|
|
|
|
|
|
print("ℹ To show repo status :\nmake repo_show_status")
|
|
|
|
|
|
input("💬 Check migration code, press to continue : ")
|
|
|
|
|
|
|
|
|
|
|
|
# source_module_path = dct_module_result.get(
|
|
|
|
|
|
# "source_module_path"
|
|
|
|
|
|
# )
|
|
|
|
|
|
# if not source_module_path:
|
|
|
|
|
|
# _logger.error(
|
|
|
|
|
|
# f"Missing source module path '{source_module_path}'"
|
|
|
|
|
|
# )
|
|
|
|
|
|
# else:
|
|
|
|
|
|
# if os.path.exists(
|
|
|
|
|
|
# os.path.join(source_module_path, ".git")
|
|
|
|
|
|
# ):
|
|
|
|
|
|
# self.todo_upgrade_execute(
|
|
|
|
|
|
# f"cd '{source_module_path}' && git stash && cd ~-",
|
|
|
|
|
|
# )
|
|
|
|
|
|
#
|
|
|
|
|
|
# target_module_path = dct_module_result.get(
|
|
|
|
|
|
# "target_module_path"
|
|
|
|
|
|
# )
|
|
|
|
|
|
# if not target_module_path:
|
|
|
|
|
|
# _logger.error(
|
|
|
|
|
|
# f"Missing target module path '{target_module_path}'"
|
|
|
|
|
|
# )
|
|
|
|
|
|
# else:
|
|
|
|
|
|
# # TODO check if has file to commit
|
|
|
|
|
|
# self.todo_upgrade_execute(
|
|
|
|
|
|
# f"cd '{target_module_path}' && git commit -am '[MIG] {len(lst_module_to_migrate_all)} modules: Migration to {next_version}' && cd ~-",
|
|
|
|
|
|
# )
|
|
|
|
|
|
|
|
|
|
|
|
# TODO copie to next odoo version
|
|
|
|
|
|
# do commit and continue
|
|
|
|
|
|
# continue migration to loop
|
|
|
|
|
|
|
|
|
|
|
|
if next_version in [18]:
|
|
|
|
|
|
# TODO need odoo 18, validate python version without switch
|
|
|
|
|
|
status = input(
|
|
|
|
|
|
f"💬 Please validate repo is ready to run upgrade views_migration_18, press to continue : "
|
|
|
|
|
|
).strip()
|
|
|
|
|
|
# Apply modification with views_migration_18
|
|
|
|
|
|
has_cmd = False
|
|
|
|
|
|
# cmd_serial = ""
|
|
|
|
|
|
cmd_parallel = "parallel :::"
|
|
|
|
|
|
for path_git_clone_migrate in lst_path_git_clone_migrate:
|
|
|
|
|
|
cmd_migration = (
|
|
|
|
|
|
f"echo 'views_migration_18 {path_git_clone_migrate}' && "
|
|
|
|
|
|
f"./.venv.odoo18.0_python3.12.10/bin/python ./script/code/odoo_upgrade_code_with_dir_module.py --path {path_git_clone_migrate}"
|
|
|
|
|
|
)
|
|
|
|
|
|
cmd_parallel += f' "{cmd_migration}"'
|
|
|
|
|
|
# cmd_serial += f"{cmd_migration};"
|
|
|
|
|
|
has_cmd = True
|
|
|
|
|
|
|
|
|
|
|
|
if has_cmd:
|
|
|
|
|
|
# self.todo_upgrade_execute(
|
|
|
|
|
|
# cmd_serial
|
|
|
|
|
|
# )
|
|
|
|
|
|
self.todo_upgrade_execute(cmd_parallel)
|
|
|
|
|
|
print("List of module with migration 18 :")
|
|
|
|
|
|
print(lst_module_to_migrate_all)
|
|
|
|
|
|
print("ℹ To show repo status :\nmake repo_show_status")
|
|
|
|
|
|
input("💬 Check migration 18 code, press to continue : ")
|
|
|
|
|
|
|
|
|
|
|
|
if next_version == 17:
|
|
|
|
|
|
status = input(
|
|
|
|
|
|
f"💬 Please validate repo is ready to run upgrade views_migration_17, press to continue : "
|
|
|
|
|
|
).strip()
|
|
|
|
|
|
# Apply modification with views_migration_17
|
|
|
|
|
|
has_cmd = False
|
|
|
|
|
|
cmd_serial = ""
|
|
|
|
|
|
cmd_parallel = "parallel :::"
|
|
|
|
|
|
for dct_module in lst_module_to_migrate_all:
|
|
|
|
|
|
database_migration_17_name = (
|
|
|
|
|
|
f"migration_odoo_{next_version}_{str(uuid4())[:6]}"
|
|
|
|
|
|
)
|
|
|
|
|
|
module_name = dct_module.get("module_name")
|
|
|
|
|
|
cmd_migration = (
|
|
|
|
|
|
f"echo 'views_migration_17 {module_name}' && "
|
|
|
|
|
|
f"./run.sh -d {database_migration_17_name} -i {module_name} --load=base,web,views_migration_17 --dev upgrade --no-http --stop-after-init"
|
|
|
|
|
|
)
|
|
|
|
|
|
cmd_parallel += f' "{cmd_migration}"'
|
|
|
|
|
|
cmd_serial += f"{cmd_migration};"
|
|
|
|
|
|
has_cmd = True
|
|
|
|
|
|
|
|
|
|
|
|
if has_cmd:
|
|
|
|
|
|
# self.todo_upgrade_execute(
|
|
|
|
|
|
# cmd_serial
|
|
|
|
|
|
# )
|
|
|
|
|
|
self.todo_upgrade_execute(cmd_parallel)
|
|
|
|
|
|
print("List of module with migration 17 :")
|
|
|
|
|
|
print(lst_module_to_migrate_all)
|
|
|
|
|
|
print("ℹ To show repo status :\nmake repo_show_status")
|
|
|
|
|
|
input("💬 Check migration 17 code, press to continue : ")
|
|
|
|
|
|
|
|
|
|
|
|
def execute_odoo_upgrade(self):
|
|
|
|
|
|
# TODO update dev environment for git project
|
|
|
|
|
|
# TODO Redeploy new production after upgrade
|
|
|
|
|
|
# 2 upgrades version = 5 environnement. 0-prod init, 1-dev init, 2-dev01, 3-dev02, 4-prod final
|
|
|
|
|
|
print("Welcome to Odoo database upgrade processus with ERPLibre 🤖")
|
|
|
|
|
|
self.lst_command_executed = []
|
|
|
|
|
|
self.dct_module_per_version = {}
|
|
|
|
|
|
self.dct_module_per_dct_version_path = {}
|
|
|
|
|
|
default_database_name = "test"
|
|
|
|
|
|
|
|
|
|
|
|
if os.path.exists(UPGRADE_DATABASE_CONFIG_LOG):
|
|
|
|
|
|
with open(UPGRADE_DATABASE_CONFIG_LOG, "r") as f:
|
|
|
|
|
|
try:
|
|
|
|
|
|
old_dct_progression = json.load(f)
|
|
|
|
|
|
self.dct_progression = {
|
|
|
|
|
|
"migration_file": old_dct_progression.get(
|
|
|
|
|
|
"migration_file"
|
|
|
|
|
|
),
|
|
|
|
|
|
# More useful to ask this question each time
|
|
|
|
|
|
"target_odoo_version": old_dct_progression.get(
|
|
|
|
|
|
"target_odoo_version"
|
|
|
|
|
|
),
|
|
|
|
|
|
"date_create": old_dct_progression.get("date_create"),
|
|
|
|
|
|
}
|
|
|
|
|
|
except json.decoder.JSONDecodeError:
|
|
|
|
|
|
print(
|
|
|
|
|
|
f'⚠️ The config file "{UPGRADE_DATABASE_CONFIG_LOG}" is invalid, ignore it.'
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
print(
|
|
|
|
|
|
f"✨ Detected migration \"{self.dct_progression.get('migration_file')}\" "
|
|
|
|
|
|
f"to version \"{self.dct_progression.get('target_odoo_version')}\", "
|
|
|
|
|
|
f"please select an option."
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
print("[1] Erase progression for a new migration")
|
|
|
|
|
|
print("[2] Reuse database with new process")
|
|
|
|
|
|
print(
|
|
|
|
|
|
"[3] Reuse database without state_4, before looping on next version"
|
|
|
|
|
|
)
|
|
|
|
|
|
print("[4] Reuse database without configuration")
|
|
|
|
|
|
erase_progression_input = (
|
|
|
|
|
|
input("💬 Select an option or press to continue : ")
|
|
|
|
|
|
.strip()
|
|
|
|
|
|
.lower()
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_progression = {}
|
|
|
|
|
|
if erase_progression_input in ["2", "3", "4"]:
|
|
|
|
|
|
with open(UPGRADE_DATABASE_CONFIG_LOG, "r") as f:
|
|
|
|
|
|
try:
|
|
|
|
|
|
old_dct_progression = json.load(f)
|
|
|
|
|
|
self.dct_progression = {
|
|
|
|
|
|
"migration_file": old_dct_progression.get(
|
|
|
|
|
|
"migration_file"
|
|
|
|
|
|
),
|
|
|
|
|
|
# More useful to ask this question each time
|
|
|
|
|
|
# "target_odoo_version": old_dct_progression.get(
|
|
|
|
|
|
# "target_odoo_version"
|
|
|
|
|
|
# ),
|
|
|
|
|
|
"date_create": old_dct_progression.get(
|
|
|
|
|
|
"date_create"
|
|
|
|
|
|
),
|
|
|
|
|
|
}
|
|
|
|
|
|
for key, value in old_dct_progression.items():
|
|
|
|
|
|
if erase_progression_input == "3":
|
|
|
|
|
|
if (
|
|
|
|
|
|
key.startswith("state_0")
|
|
|
|
|
|
or key.startswith("state_1")
|
|
|
|
|
|
or key.startswith("state_2")
|
|
|
|
|
|
or key.startswith("state_3")
|
|
|
|
|
|
):
|
|
|
|
|
|
self.dct_progression[key] = value
|
|
|
|
|
|
if key.startswith(f"config_state") and not (
|
|
|
|
|
|
key.startswith(f"config_state_0")
|
|
|
|
|
|
or key.startswith(f"config_state_1")
|
|
|
|
|
|
or key.startswith(f"config_state_2")
|
|
|
|
|
|
or key.startswith(f"config_state_3")
|
|
|
|
|
|
):
|
|
|
|
|
|
continue
|
|
|
|
|
|
if (
|
|
|
|
|
|
key.startswith("config_")
|
|
|
|
|
|
and erase_progression_input != "4"
|
|
|
|
|
|
):
|
|
|
|
|
|
self.dct_progression[key] = value
|
|
|
|
|
|
# Force to search missing module to fill dict
|
|
|
|
|
|
self.dct_progression[
|
|
|
|
|
|
"state_0_search_missing_module"
|
|
|
|
|
|
] = False
|
|
|
|
|
|
except json.decoder.JSONDecodeError:
|
|
|
|
|
|
print(
|
|
|
|
|
|
f"⚠️ The config file '{UPGRADE_DATABASE_CONFIG_LOG}' is invalid, ignore it."
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
elif erase_progression_input not in ["1"]:
|
|
|
|
|
|
with open(UPGRADE_DATABASE_CONFIG_LOG, "r") as f:
|
|
|
|
|
|
try:
|
|
|
|
|
|
self.dct_progression = json.load(f)
|
|
|
|
|
|
except json.decoder.JSONDecodeError:
|
|
|
|
|
|
print(
|
|
|
|
|
|
f"⚠️ The config file '{UPGRADE_DATABASE_CONFIG_LOG}' is invalid, ignore it."
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if "migration_file" in self.dct_progression:
|
|
|
|
|
|
self.file_path = self.dct_progression["migration_file"]
|
|
|
|
|
|
else:
|
|
|
|
|
|
print("")
|
|
|
|
|
|
print("Select the zip file of you database backup.")
|
|
|
|
|
|
|
|
|
|
|
|
self.file_path = input(
|
|
|
|
|
|
"💬 Give the path of file, or empty to use a File Browser, or type 'remote' to download from production : "
|
|
|
|
|
|
)
|
|
|
|
|
|
if not self.file_path.strip():
|
|
|
|
|
|
self.file_path = None
|
|
|
|
|
|
if not self.file_path:
|
|
|
|
|
|
initial_dir = os.path.join(os.getcwd(), "image_db")
|
|
|
|
|
|
file_browser = todo_file_browser.FileBrowser(
|
|
|
|
|
|
initial_dir, self.on_file_selected
|
|
|
|
|
|
)
|
|
|
|
|
|
file_browser.run_main_frame()
|
|
|
|
|
|
elif self.file_path == "remote":
|
|
|
|
|
|
status, self.file_path, default_database_name = (
|
2026-05-20 02:54:29 -04:00
|
|
|
|
self.todo.db_manager.download_database_backup_cli()
|
2025-10-31 01:10:54 -04:00
|
|
|
|
)
|
|
|
|
|
|
if status:
|
|
|
|
|
|
_logger.error(
|
|
|
|
|
|
"Cannot retrieve database from remote, please retry migration."
|
|
|
|
|
|
)
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
self.dct_progression["migration_file"] = self.file_path
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
print(f"✅ Open file {self.file_path}")
|
|
|
|
|
|
with zipfile.ZipFile(self.file_path, "r") as zip_ref:
|
|
|
|
|
|
manifest_file_1 = zip_ref.open("manifest.json")
|
|
|
|
|
|
json_manifest_file_1 = json.load(manifest_file_1)
|
|
|
|
|
|
odoo_actual_version = json_manifest_file_1.get("version")
|
|
|
|
|
|
print(f"✅ Detect version Odoo CE '{odoo_actual_version}'.")
|
|
|
|
|
|
|
|
|
|
|
|
# print("What is your actual Odoo version?")
|
|
|
|
|
|
lst_version, lst_version_installed, odoo_installed_version = (
|
2026-03-26 15:45:44 -04:00
|
|
|
|
get_odoo_version()
|
2025-10-31 01:10:54 -04:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
lst_odoo_version = [
|
|
|
|
|
|
{"prompt_description": a.get("odoo_version")}
|
|
|
|
|
|
for a in lst_version
|
|
|
|
|
|
if float(a.get("odoo_version")) > float(odoo_actual_version)
|
|
|
|
|
|
]
|
|
|
|
|
|
help_info = self.todo.fill_help_info(lst_odoo_version)
|
|
|
|
|
|
|
|
|
|
|
|
if "target_odoo_version" in self.dct_progression:
|
|
|
|
|
|
odoo_target_version = self.dct_progression["target_odoo_version"]
|
|
|
|
|
|
else:
|
|
|
|
|
|
print("💬 Which version do you want to upgrade to?")
|
|
|
|
|
|
odoo_target_version = None
|
|
|
|
|
|
cmd_no_found = True
|
|
|
|
|
|
while cmd_no_found:
|
|
|
|
|
|
status = click.prompt(help_info)
|
|
|
|
|
|
try:
|
|
|
|
|
|
int_cmd = int(status)
|
|
|
|
|
|
if 0 < int_cmd <= len(lst_odoo_version):
|
|
|
|
|
|
cmd_no_found = False
|
|
|
|
|
|
odoo_target_version = lst_odoo_version[
|
|
|
|
|
|
int_cmd - 1
|
|
|
|
|
|
].get("prompt_description")
|
|
|
|
|
|
except ValueError:
|
|
|
|
|
|
pass
|
|
|
|
|
|
if cmd_no_found:
|
|
|
|
|
|
print("Commande non trouvée 🤖!")
|
|
|
|
|
|
|
|
|
|
|
|
self.dct_progression["target_odoo_version"] = odoo_target_version
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
# Search nb diff to use range
|
|
|
|
|
|
start_version = int(float(odoo_actual_version))
|
|
|
|
|
|
end_version = int(float(odoo_target_version))
|
|
|
|
|
|
range_version = range(start_version, end_version)
|
|
|
|
|
|
lst_module = sorted(
|
|
|
|
|
|
list(set(json_manifest_file_1.get("modules").keys()))
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_module_per_version[start_version] = lst_module
|
|
|
|
|
|
self.dct_progression["dct_module_per_version"] = (
|
|
|
|
|
|
self.dct_module_per_version
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_progression["lst_module_per_version_origin"] = lst_module
|
|
|
|
|
|
# TODO need support minor version, example 18.2, the .2 (no need for OCE OCB)
|
|
|
|
|
|
|
|
|
|
|
|
print("✨ Show documentation version :")
|
|
|
|
|
|
# TODO Generate it locally and show it if asked
|
|
|
|
|
|
|
|
|
|
|
|
for next_version in range_version:
|
|
|
|
|
|
print(
|
|
|
|
|
|
f"https://oca.github.io/OpenUpgrade/coverage_analysis/modules{next_version*10}-{(next_version+1)*10}.html"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# ⚠️ ℹ 💬 ❗ 🔷 ✨ 🟦 🔹 🔵 ⟳ ⧖ ⚙ ✔ ✅ ❌ ⏵ ⏸ ⏹ ◆ ◇ … ➤ ⚑ ★ ☆ ☰ ⬍ ⍟ ⊗ ⌘ ⏻ ⍰
|
|
|
|
|
|
msg = "0 - Inspect zip"
|
|
|
|
|
|
print(f"🔷 {msg}")
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
print("✅ -> Search odoo version")
|
|
|
|
|
|
print("✅ -> Find good environment, read the .zip file")
|
|
|
|
|
|
|
|
|
|
|
|
is_state_4_reach_open_upgrade = self.dct_progression.get(
|
|
|
|
|
|
"state_4_reach_open_upgrade"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if not is_state_4_reach_open_upgrade and not self.dct_progression.get(
|
|
|
|
|
|
"state_0_install_odoo"
|
|
|
|
|
|
):
|
|
|
|
|
|
lst_diff_version = sorted(
|
|
|
|
|
|
list(
|
|
|
|
|
|
set([f"odoo{a}.0" for a in range_version]).difference(
|
|
|
|
|
|
set(lst_version_installed)
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
for odoo_version_to_install in lst_diff_version:
|
|
|
|
|
|
iter_range_version = odoo_version_to_install.replace(
|
|
|
|
|
|
"odoo", ""
|
|
|
|
|
|
).replace(".0", "")
|
|
|
|
|
|
want_continue = input(
|
|
|
|
|
|
f"💬 Would you like to install '{odoo_version_to_install}' (y/Y) : "
|
|
|
|
|
|
)
|
|
|
|
|
|
if want_continue.strip().lower() != "y":
|
|
|
|
|
|
return
|
|
|
|
|
|
self.todo_upgrade_execute(
|
|
|
|
|
|
f"make install_odoo_{iter_range_version}"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if not os.path.isfile(FILENAME_ODOO_VERSION):
|
|
|
|
|
|
print(
|
|
|
|
|
|
"⚠️ You need an installed system before continue, check your Odoo installation."
|
|
|
|
|
|
)
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
self.dct_progression["state_0_install_odoo"] = True
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
# not self.dct_progression.get("state_0_switch_odoo")
|
|
|
|
|
|
if not is_state_4_reach_open_upgrade:
|
|
|
|
|
|
self.switch_odoo(odoo_actual_version)
|
|
|
|
|
|
# self.dct_progression["state_0_switch_odoo"] = True
|
|
|
|
|
|
# self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
print("✅ -> Install environment if missing")
|
|
|
|
|
|
|
|
|
|
|
|
if not self.dct_progression.get("state_0_search_missing_module"):
|
|
|
|
|
|
self.switch_odoo(odoo_actual_version)
|
|
|
|
|
|
dct_bd_modules = json_manifest_file_1.get("modules")
|
|
|
|
|
|
lst_module_to_check = [a for a in dct_bd_modules.keys()]
|
|
|
|
|
|
(
|
|
|
|
|
|
lst_module_missing,
|
|
|
|
|
|
lst_module_duplicate,
|
|
|
|
|
|
lst_module_exist,
|
|
|
|
|
|
lst_module_error,
|
|
|
|
|
|
) = self.check_addons_exist(lst_module_to_check, get_all_info=True)
|
|
|
|
|
|
if not lst_module_missing:
|
|
|
|
|
|
lst_module_missing = []
|
|
|
|
|
|
dct_module_exist = {}
|
|
|
|
|
|
if not lst_module_exist:
|
|
|
|
|
|
lst_module_exist = []
|
|
|
|
|
|
else:
|
|
|
|
|
|
for item_lst_module_exist in lst_module_exist:
|
|
|
|
|
|
dct_module_exist[item_lst_module_exist[0]] = (
|
|
|
|
|
|
item_lst_module_exist[1].replace(os.getcwd(), ".")
|
|
|
|
|
|
)
|
|
|
|
|
|
if not lst_module_duplicate:
|
|
|
|
|
|
lst_module_duplicate = []
|
|
|
|
|
|
|
|
|
|
|
|
lst_module_missing = sorted(list(set(lst_module_missing)))
|
|
|
|
|
|
self.dct_progression["len_lst_module_missing"] = len(
|
|
|
|
|
|
lst_module_missing
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_progression["lst_module_missing"] = lst_module_missing
|
|
|
|
|
|
self.dct_progression["len_dct_module_exist"] = len(
|
|
|
|
|
|
lst_module_exist
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_progression["dct_module_exist"] = dct_module_exist
|
|
|
|
|
|
self.dct_progression["len_lst_module_duplicate"] = len(
|
|
|
|
|
|
lst_module_duplicate
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
self.dct_progression["lst_module_duplicate"] = lst_module_duplicate
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
if lst_module_missing or lst_module_duplicate:
|
|
|
|
|
|
print("Cannot setup environment to begin.")
|
|
|
|
|
|
if lst_module_missing:
|
|
|
|
|
|
print("Missing module :")
|
|
|
|
|
|
print(lst_module_missing)
|
|
|
|
|
|
if lst_module_duplicate:
|
|
|
|
|
|
print("Duplicate module :")
|
|
|
|
|
|
print(lst_module_duplicate)
|
|
|
|
|
|
want_continue = input(
|
|
|
|
|
|
"💬 Detect error missing/duplicate module init, do you want to continue? (Y/N): "
|
|
|
|
|
|
)
|
|
|
|
|
|
if want_continue.strip().lower() != "y":
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
self.dct_progression["state_0_search_missing_module"] = True
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
else:
|
|
|
|
|
|
# TODO fill from config
|
|
|
|
|
|
lst_module_missing = []
|
|
|
|
|
|
|
|
|
|
|
|
print("✅ -> Search missing module")
|
|
|
|
|
|
|
|
|
|
|
|
print(
|
|
|
|
|
|
"❌ -> Install missing module, do a research or ask to uninstall it (can break data)"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
msg = "1 - Import database from zip"
|
|
|
|
|
|
print(f"🔷 {msg}")
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
database_name = self.dct_progression.get("config_database_name")
|
|
|
|
|
|
if not database_name:
|
|
|
|
|
|
database_name = (
|
|
|
|
|
|
input(
|
|
|
|
|
|
f"💬 Witch database name do you want to work with? Default ({default_database_name}) : "
|
|
|
|
|
|
).strip()
|
|
|
|
|
|
or default_database_name
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_progression["config_database_name"] = database_name
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
do_neutralize = False
|
|
|
|
|
|
if not self.dct_progression.get("state_1_neutralize_database"):
|
|
|
|
|
|
print("[1] Ignore neutralize database")
|
|
|
|
|
|
wait_continue = (
|
|
|
|
|
|
input("💬 Neutralize database, press to continue : ")
|
|
|
|
|
|
.strip()
|
|
|
|
|
|
.lower()
|
|
|
|
|
|
)
|
|
|
|
|
|
if wait_continue != "1":
|
|
|
|
|
|
do_neutralize = True
|
|
|
|
|
|
database_name += "_neutralize"
|
|
|
|
|
|
self.dct_progression["config_database_name"] = database_name
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
print(f"★ Work with database '{database_name}'")
|
|
|
|
|
|
|
|
|
|
|
|
if not self.dct_progression.get("state_1_restore_database"):
|
|
|
|
|
|
file_name = os.path.basename(self.file_path)
|
|
|
|
|
|
image_db_file_path = os.path.join("image_db", file_name)
|
2026-01-05 07:52:30 -05:00
|
|
|
|
str_will_copy = (
|
|
|
|
|
|
f"🤖 will copy '{self.file_path}' to '{image_db_file_path}'"
|
|
|
|
|
|
)
|
|
|
|
|
|
if not shutil._samefile(self.file_path, image_db_file_path):
|
|
|
|
|
|
do_copy = False
|
|
|
|
|
|
if os.path.exists(image_db_file_path):
|
2025-10-31 01:10:54 -04:00
|
|
|
|
status_overwrite_image_db = input(
|
2026-01-05 07:52:30 -05:00
|
|
|
|
f"{str_will_copy}, "
|
2025-10-31 01:10:54 -04:00
|
|
|
|
f"a file already exist, do you want to continue (y/Y) : "
|
|
|
|
|
|
).strip()
|
2026-01-05 07:52:30 -05:00
|
|
|
|
if status_overwrite_image_db.lower() == "y":
|
|
|
|
|
|
do_copy = True
|
|
|
|
|
|
os.remove(image_db_file_path)
|
|
|
|
|
|
else:
|
|
|
|
|
|
print(str_will_copy)
|
|
|
|
|
|
do_copy = True
|
|
|
|
|
|
|
|
|
|
|
|
if do_copy:
|
2025-10-31 01:10:54 -04:00
|
|
|
|
shutil.copy(self.file_path, image_db_file_path)
|
|
|
|
|
|
|
2026-02-22 12:14:07 -05:00
|
|
|
|
neutralize_arg = ""
|
|
|
|
|
|
if start_version >= 16 and do_neutralize:
|
|
|
|
|
|
neutralize_arg = " --neutralize"
|
|
|
|
|
|
|
2025-10-31 01:10:54 -04:00
|
|
|
|
status, cmd_executed = self.todo_upgrade_execute(
|
2026-02-22 12:14:07 -05:00
|
|
|
|
f"./script/database/db_restore.py --database {database_name} --image {file_name} --ignore_cache{neutralize_arg}",
|
2025-10-31 01:10:54 -04:00
|
|
|
|
single_source_odoo=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
if not status:
|
|
|
|
|
|
self.dct_progression["state_1_restore_database"] = True
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
print("✅ -> Restore database")
|
|
|
|
|
|
|
|
|
|
|
|
print("✅ -> Neutralize database")
|
|
|
|
|
|
if do_neutralize:
|
|
|
|
|
|
status, cmd_executed = self.todo_upgrade_execute(
|
|
|
|
|
|
f"./script/addons/update_prod_to_dev.sh {database_name}",
|
|
|
|
|
|
single_source_odoo=True,
|
|
|
|
|
|
)
|
2026-02-22 12:14:07 -05:00
|
|
|
|
|
|
|
|
|
|
# TODO exécuter next line si status != 0 et log contient
|
|
|
|
|
|
# psycopg2.errors.UndefinedTable: relation "discuss_channel" does not exist
|
|
|
|
|
|
# LIGNE 1 : SELECT "discuss_channel"."id" FROM "discuss_channel" WHERE (...
|
|
|
|
|
|
# source ./.venv.odoo18.0_python3.12.10/bin/activate && cat script/postgresql/migration/fix_migration_postgresql_17_to_postgresql_18_module_mail_nov_2025.py | ./odoo18.0/odoo/odoo-bin shell -d ripbylop_stage_prod_17_nov_2025
|
|
|
|
|
|
# psycopg2.errors.ForeignKeyViolation: insert or update on table "discuss_channel_member" violates foreign key constraint "discuss_channel_member_channel_id_fkey"
|
|
|
|
|
|
# DÉTAIL : Key (channel_id)=(20) is not present in table "discuss_channel".
|
|
|
|
|
|
# ./script/database/migrate/process_backup_file.py --path_backup_zip image_db/db.zip --path_output_zip image_db/dbFIX.zip --word_to_delete discuss_channel_channel_type_not_null
|
|
|
|
|
|
# Puis faire un retry de la commande, sinon rien
|
|
|
|
|
|
|
2025-10-31 01:10:54 -04:00
|
|
|
|
self.dct_progression["state_1_neutralize_database"] = True
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
if not status:
|
|
|
|
|
|
self.dct_progression["state_1_neutralize_database"] = True
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
else:
|
|
|
|
|
|
self.dct_progression["state_1_neutralize_database"] = True
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
config_state_1_uninstall_module = self.dct_progression.get(
|
|
|
|
|
|
"config_state_1_uninstall_module"
|
|
|
|
|
|
)
|
|
|
|
|
|
config_state_1_install_module = self.dct_progression.get(
|
|
|
|
|
|
"config_state_1_install_module"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if not is_state_4_reach_open_upgrade:
|
|
|
|
|
|
lst_module_to_uninstall = []
|
|
|
|
|
|
uninstall_module_list_file = os.path.join(
|
|
|
|
|
|
"script",
|
|
|
|
|
|
"odoo",
|
|
|
|
|
|
"migration",
|
|
|
|
|
|
f"uninstall_module_list_odoo{start_version * 10}_to_odoo{(start_version + 1) * 10}.txt",
|
|
|
|
|
|
)
|
|
|
|
|
|
if os.path.exists(uninstall_module_list_file):
|
|
|
|
|
|
with open(uninstall_module_list_file, "r") as f:
|
|
|
|
|
|
lst_module_to_uninstall = [
|
|
|
|
|
|
a.strip() for a in f.readline().split()
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
if config_state_1_uninstall_module:
|
|
|
|
|
|
lst_module_to_uninstall = (
|
|
|
|
|
|
lst_module_to_uninstall + config_state_1_uninstall_module
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if lst_module_to_uninstall:
|
|
|
|
|
|
self.uninstall_from_database(
|
|
|
|
|
|
lst_module_to_uninstall, database_name, start_version
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_progression["state_1_uninstall_module"] = True
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
self.dct_progression["config_state_1_uninstall_module"] = (
|
|
|
|
|
|
config_state_1_uninstall_module
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
print("✅ -> Uninstall module")
|
|
|
|
|
|
|
|
|
|
|
|
print("✅ -> install module")
|
|
|
|
|
|
if not is_state_4_reach_open_upgrade:
|
|
|
|
|
|
lst_module_to_install = []
|
|
|
|
|
|
if config_state_1_install_module:
|
|
|
|
|
|
lst_module_to_install = (
|
|
|
|
|
|
lst_module_to_install + config_state_1_install_module
|
|
|
|
|
|
)
|
|
|
|
|
|
if lst_module_to_install:
|
|
|
|
|
|
self.install_from_database(
|
|
|
|
|
|
lst_module_to_install, database_name, start_version
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_progression["state_1_install_module"] = True
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
self.dct_progression["config_state_1_install_module"] = (
|
|
|
|
|
|
config_state_1_install_module
|
|
|
|
|
|
)
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
msg = "2 - Succeed update all addons"
|
|
|
|
|
|
print(f"🔷 {msg}")
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
if not self.dct_progression.get("state_2_update_all"):
|
|
|
|
|
|
status, cmd_executed = self.todo_upgrade_execute(
|
|
|
|
|
|
f"./script/addons/update_addons_all.sh {database_name}",
|
|
|
|
|
|
single_source_odoo=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
if not status:
|
|
|
|
|
|
self.dct_progression["state_2_update_all"] = True
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
msg = "3 - Clean up database before data migration"
|
|
|
|
|
|
print(f"🔷 {msg}")
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
if not self.dct_progression.get("state_3_install_clean_database"):
|
|
|
|
|
|
status, cmd_executed = self.todo_upgrade_execute(
|
|
|
|
|
|
f"./script/addons/install_addons.sh {database_name} database_cleanup",
|
|
|
|
|
|
single_source_odoo=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
if not status:
|
|
|
|
|
|
self.dct_progression["state_3_install_clean_database"] = True
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
if not self.dct_progression.get("state_3_clean_database"):
|
|
|
|
|
|
print(
|
|
|
|
|
|
"✨ Aller dans «configuration/Technique/Nettoyage.../Purger» les modules obsolètes"
|
|
|
|
|
|
)
|
|
|
|
|
|
status = input(
|
|
|
|
|
|
"💬 Did you finish to clean database? Press y/Y to open server with selenium, else ignore it : "
|
|
|
|
|
|
).strip()
|
|
|
|
|
|
|
|
|
|
|
|
if status.lower().strip() == "y":
|
|
|
|
|
|
self.todo.prompt_execute_selenium_and_run_db(database_name)
|
|
|
|
|
|
status = input("💬 Press to continue state.3 : ").strip()
|
|
|
|
|
|
|
|
|
|
|
|
self.dct_progression["state_3_clean_database"] = True
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
self.install_OCA_odoo_module_migrator()
|
|
|
|
|
|
|
|
|
|
|
|
msg = "4 - Upgrade version with OpenUpgrade"
|
|
|
|
|
|
print(f"🔷 {msg}")
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
self.dct_progression["state_4_reach_open_upgrade"] = True
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
lst_next_version = [
|
|
|
|
|
|
a for a in range(start_version + 1, end_version + 1)
|
|
|
|
|
|
]
|
|
|
|
|
|
lst_database_name_upgrade = [
|
|
|
|
|
|
f"{database_name}_upgrade_{str(a)}" for a in lst_next_version
|
|
|
|
|
|
]
|
|
|
|
|
|
# Setup lst_switch_odoo
|
|
|
|
|
|
lst_clone_odoo = self.dct_progression.get(
|
|
|
|
|
|
"state_4_clone_odoo_lst", [False] * len(lst_next_version)
|
|
|
|
|
|
)
|
|
|
|
|
|
lst_switch_odoo = self.dct_progression.get(
|
|
|
|
|
|
"state_4_switch_odoo_lst", [False] * len(lst_next_version)
|
|
|
|
|
|
)
|
|
|
|
|
|
lst_module_migrate_odoo = self.dct_progression.get(
|
|
|
|
|
|
"state_4_module_migrate_odoo_lst", [False] * len(lst_next_version)
|
|
|
|
|
|
)
|
|
|
|
|
|
lst_module_uninstall_module = self.dct_progression.get(
|
|
|
|
|
|
"state_4_uninstall_module", [False] * len(lst_next_version)
|
|
|
|
|
|
)
|
|
|
|
|
|
lst_module_install_module = self.dct_progression.get(
|
|
|
|
|
|
"state_4_install_module", [False] * len(lst_next_version)
|
|
|
|
|
|
)
|
|
|
|
|
|
lst_module_search_missing_module = self.dct_progression.get(
|
|
|
|
|
|
"state_4_search_missing_module", [False] * len(lst_next_version)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
nb_missing_value_switch_odoo = abs(
|
|
|
|
|
|
len(lst_switch_odoo) - len(lst_next_version)
|
|
|
|
|
|
)
|
|
|
|
|
|
if nb_missing_value_switch_odoo:
|
|
|
|
|
|
lst_switch_odoo += [False] * nb_missing_value_switch_odoo
|
|
|
|
|
|
|
|
|
|
|
|
# Setup lst_upgrade_odoo
|
|
|
|
|
|
lst_upgrade_odoo = self.dct_progression.get(
|
|
|
|
|
|
"state_4_upgrade_odoo_lst", [[]] * len(lst_next_version)
|
|
|
|
|
|
)
|
|
|
|
|
|
lst_fix_migration_odoo = self.dct_progression.get(
|
|
|
|
|
|
"state_4_fix_migration_odoo_lst", [[]] * len(lst_next_version)
|
|
|
|
|
|
)
|
|
|
|
|
|
nb_missing_value_upgrade_odoo = abs(
|
|
|
|
|
|
len(lst_upgrade_odoo) - len(lst_next_version)
|
|
|
|
|
|
)
|
|
|
|
|
|
if nb_missing_value_upgrade_odoo:
|
|
|
|
|
|
lst_upgrade_odoo += [[]] * nb_missing_value_upgrade_odoo
|
|
|
|
|
|
|
|
|
|
|
|
database_name_upgrade = None
|
|
|
|
|
|
lst_module_missing_next_version = []
|
|
|
|
|
|
lst_module_to_delete = []
|
|
|
|
|
|
lst_module_to_delete_last_version = []
|
|
|
|
|
|
for index, next_version in enumerate(lst_next_version):
|
|
|
|
|
|
# Reinit the list
|
|
|
|
|
|
lst_module_missing_last_version = lst_module_missing_next_version[
|
|
|
|
|
|
:
|
|
|
|
|
|
]
|
|
|
|
|
|
lst_module_to_delete_last_version.extend(lst_module_to_delete)
|
|
|
|
|
|
lst_module_to_delete = []
|
|
|
|
|
|
|
|
|
|
|
|
msg = f"4.{index} - Ready to work with version {next_version}"
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
option_comment = 0
|
|
|
|
|
|
msg = f"4.{index}.{chr(option_comment + 65)} - Search updated module list to next version"
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
if not database_name_upgrade:
|
|
|
|
|
|
last_database_name = database_name
|
|
|
|
|
|
else:
|
|
|
|
|
|
last_database_name = database_name_upgrade
|
|
|
|
|
|
database_name_upgrade = lst_database_name_upgrade[index]
|
|
|
|
|
|
lst_module_to_uninstall = []
|
|
|
|
|
|
lst_module_to_install = []
|
|
|
|
|
|
lst_module_to_analyse = self.get_rename_module(
|
|
|
|
|
|
self.dct_module_per_version[next_version - 1],
|
|
|
|
|
|
next_version,
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_module_per_version[next_version] = sorted(
|
|
|
|
|
|
list(set(lst_module_to_analyse))
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_progression["dct_module_per_version"] = (
|
|
|
|
|
|
self.dct_module_per_version
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
option_comment += 1
|
|
|
|
|
|
msg = f"4.{index}.{chr(option_comment + 65)} - Clone Odoo"
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(f"odoo{next_version}.0/addons/addons"):
|
|
|
|
|
|
os.makedirs(f"odoo{next_version}.0/addons/addons")
|
|
|
|
|
|
|
|
|
|
|
|
if not lst_clone_odoo[index]:
|
|
|
|
|
|
self.switch_odoo(next_version - 1)
|
|
|
|
|
|
|
|
|
|
|
|
print(
|
|
|
|
|
|
f"⧖ -> Clone to odoo.'{next_version}', from '{database_name}' to '{database_name_upgrade}'."
|
|
|
|
|
|
)
|
|
|
|
|
|
# Delete if exist database
|
|
|
|
|
|
self.todo_upgrade_execute(
|
|
|
|
|
|
f"./script/database/db_restore.py -d {database_name_upgrade} --only_drop",
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# Duplicate database
|
|
|
|
|
|
cmd_clone_database = f"./odoo_bin.sh db --clone --from_database {last_database_name} --database {database_name_upgrade}"
|
|
|
|
|
|
self.todo_upgrade_execute(cmd_clone_database)
|
|
|
|
|
|
|
|
|
|
|
|
lst_clone_odoo[index] = True
|
|
|
|
|
|
self.dct_progression["state_4_clone_odoo_lst"] = lst_clone_odoo
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
print(f"✅ -> Clone Odoo{next_version} done")
|
|
|
|
|
|
else:
|
|
|
|
|
|
print(f"✅ -> Clone Odoo{next_version} - nothing")
|
|
|
|
|
|
|
|
|
|
|
|
option_comment += 1
|
|
|
|
|
|
msg = f"4.{index}.{chr(option_comment + 65)} - Uninstall module"
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
config_state_4_uninstall_module = self.dct_progression.get(
|
|
|
|
|
|
"config_state_4_uninstall_module",
|
|
|
|
|
|
[False] * len(lst_next_version),
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if not lst_module_uninstall_module[index]:
|
|
|
|
|
|
lst_module_to_uninstall = config_state_4_uninstall_module[
|
|
|
|
|
|
index
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
if lst_module_to_uninstall:
|
|
|
|
|
|
self.uninstall_from_database(
|
|
|
|
|
|
lst_module_to_uninstall,
|
|
|
|
|
|
database_name_upgrade,
|
|
|
|
|
|
next_version - 1,
|
|
|
|
|
|
)
|
|
|
|
|
|
lst_module_uninstall_module[index] = True
|
|
|
|
|
|
self.dct_progression["state_4_module_migrate_odoo_lst"] = (
|
|
|
|
|
|
lst_module_uninstall_module
|
|
|
|
|
|
)
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
self.dct_progression["config_state_4_uninstall_module"] = (
|
|
|
|
|
|
config_state_4_uninstall_module
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_progression["state_4_uninstall_module"] = (
|
|
|
|
|
|
lst_module_uninstall_module
|
|
|
|
|
|
)
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
option_comment += 1
|
|
|
|
|
|
msg = f"4.{index}.{chr(option_comment + 65)} - Install module"
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
config_state_4_install_module = self.dct_progression.get(
|
|
|
|
|
|
"config_state_4_install_module",
|
|
|
|
|
|
[False] * len(lst_next_version),
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# Special case to install module to fix migration
|
|
|
|
|
|
if (
|
|
|
|
|
|
next_version == 13
|
|
|
|
|
|
and "dms" in lst_module_to_analyse
|
|
|
|
|
|
and "muk_dms"
|
|
|
|
|
|
not in self.dct_progression.get("dct_module_exist", {}).keys()
|
|
|
|
|
|
):
|
|
|
|
|
|
# Force install dms into odoo 12
|
|
|
|
|
|
if not config_state_4_install_module[index]:
|
|
|
|
|
|
config_state_4_install_module[index] = ["dms"]
|
|
|
|
|
|
elif "dms" not in config_state_4_install_module[index]:
|
|
|
|
|
|
config_state_4_install_module[index].append("dms")
|
|
|
|
|
|
|
|
|
|
|
|
if not lst_module_install_module[index]:
|
|
|
|
|
|
lst_module_to_install = config_state_4_install_module[index]
|
|
|
|
|
|
if not lst_module_to_install:
|
|
|
|
|
|
lst_module_to_install = []
|
|
|
|
|
|
|
|
|
|
|
|
if lst_module_to_install:
|
|
|
|
|
|
self.install_from_database(
|
|
|
|
|
|
lst_module_to_install,
|
|
|
|
|
|
database_name_upgrade,
|
|
|
|
|
|
next_version - 1,
|
|
|
|
|
|
)
|
|
|
|
|
|
lst_module_install_module[index] = True
|
|
|
|
|
|
self.dct_progression["state_4_module_migrate_odoo_lst"] = (
|
|
|
|
|
|
lst_module_install_module
|
|
|
|
|
|
)
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
self.dct_progression["config_state_4_install_module"] = (
|
|
|
|
|
|
config_state_4_install_module
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_progression["state_4_install_module"] = (
|
|
|
|
|
|
lst_module_install_module
|
|
|
|
|
|
)
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
option_comment += 1
|
|
|
|
|
|
msg = f"4.{index}.{chr(option_comment + 65)} - Switch Odoo"
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
if not lst_switch_odoo[index]:
|
|
|
|
|
|
self.switch_odoo(next_version)
|
|
|
|
|
|
lst_switch_odoo[index] = True
|
|
|
|
|
|
self.dct_progression["state_4_switch_odoo_lst"] = (
|
|
|
|
|
|
lst_switch_odoo
|
|
|
|
|
|
)
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
print(f"✅ -> Switch Odoo{next_version} done with update")
|
|
|
|
|
|
else:
|
|
|
|
|
|
print(f"✅ -> Switch Odoo{next_version} - nothing")
|
|
|
|
|
|
|
|
|
|
|
|
lst_state_4_module_migrate_code = self.dct_progression.get(
|
|
|
|
|
|
"config_state_4_module_to_migrate_code",
|
|
|
|
|
|
[[]] * len(lst_next_version),
|
|
|
|
|
|
)
|
|
|
|
|
|
if (
|
|
|
|
|
|
"config_state_4_module_to_migrate_code"
|
|
|
|
|
|
not in self.dct_progression.keys()
|
|
|
|
|
|
):
|
|
|
|
|
|
self.dct_progression[
|
|
|
|
|
|
"config_state_4_module_to_migrate_code"
|
|
|
|
|
|
] = lst_state_4_module_migrate_code
|
|
|
|
|
|
lst_module_to_migrate = lst_state_4_module_migrate_code[index]
|
|
|
|
|
|
|
|
|
|
|
|
option_comment += 1
|
|
|
|
|
|
msg = (
|
|
|
|
|
|
f"4.{index}.{chr(option_comment + 65)} - Search missing module"
|
|
|
|
|
|
)
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
if not lst_module_search_missing_module[index]:
|
|
|
|
|
|
lst_module_to_analyse_updated = []
|
|
|
|
|
|
for bd_module in lst_module_to_analyse:
|
|
|
|
|
|
if (
|
|
|
|
|
|
lst_module_to_uninstall
|
|
|
|
|
|
and bd_module in lst_module_to_uninstall
|
|
|
|
|
|
):
|
|
|
|
|
|
# Ignore check if uninstall before
|
|
|
|
|
|
continue
|
|
|
|
|
|
lst_module_to_analyse_updated.append(bd_module)
|
|
|
|
|
|
|
|
|
|
|
|
# TODO remove from list past module deleted
|
|
|
|
|
|
lst_module_to_check = [
|
|
|
|
|
|
a
|
|
|
|
|
|
for a in lst_module_to_analyse_updated
|
|
|
|
|
|
if a not in lst_module_to_delete_last_version
|
|
|
|
|
|
]
|
|
|
|
|
|
(
|
|
|
|
|
|
lst_module_missing_next_version,
|
|
|
|
|
|
lst_module_duplicate_next_version,
|
|
|
|
|
|
) = self.check_addons_exist(lst_module_to_check)
|
|
|
|
|
|
|
|
|
|
|
|
lst_module_missing_next_version = sorted(
|
|
|
|
|
|
list(set(lst_module_missing_next_version))
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
self.dct_progression["state_4_len_lst_module_missing"] = len(
|
|
|
|
|
|
lst_module_missing_next_version
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_progression["state_4_lst_module_missing"] = (
|
|
|
|
|
|
lst_module_missing_next_version
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
lst_module_duplicate = sorted(
|
|
|
|
|
|
list(set(lst_module_duplicate_next_version))
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
self.dct_progression["state_4_len_lst_module_duplicate"] = len(
|
|
|
|
|
|
lst_module_duplicate
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_progression["state_4_lst_module_duplicate"] = (
|
|
|
|
|
|
lst_module_duplicate
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if lst_module_duplicate:
|
|
|
|
|
|
print(f"Duplicate module into odoo{next_version} : ")
|
|
|
|
|
|
print(lst_module_duplicate)
|
|
|
|
|
|
input(
|
|
|
|
|
|
f"💬 Detect error duplicate module, manage this problem manually and press to continue."
|
|
|
|
|
|
)
|
|
|
|
|
|
# if lst_module_missing_next_version and not lst_module_to_migrate:
|
|
|
|
|
|
if lst_module_missing_next_version:
|
|
|
|
|
|
# TODO support when lst_module_to_migrate is fill
|
|
|
|
|
|
lst_module_to_migrate = []
|
|
|
|
|
|
print(
|
|
|
|
|
|
f"👹 Detect error missing module, missing module into odoo{next_version} :"
|
|
|
|
|
|
)
|
|
|
|
|
|
for index_missing_module, module_missing in enumerate(
|
|
|
|
|
|
lst_module_missing_next_version
|
|
|
|
|
|
):
|
|
|
|
|
|
old_path = self.dct_progression.get(
|
|
|
|
|
|
"dct_module_exist", {}
|
|
|
|
|
|
).get(module_missing)
|
|
|
|
|
|
print(
|
|
|
|
|
|
f"[{index_missing_module}] {module_missing} - {old_path}"
|
|
|
|
|
|
)
|
|
|
|
|
|
print("[a] All list above")
|
|
|
|
|
|
print("[e] Add extra custom")
|
|
|
|
|
|
|
|
|
|
|
|
want_continue = (
|
|
|
|
|
|
input(
|
|
|
|
|
|
f"💬 Enumerate missing module separate by coma to delete it"
|
|
|
|
|
|
f". The others will be migrate : "
|
|
|
|
|
|
)
|
|
|
|
|
|
.strip()
|
|
|
|
|
|
.lower()
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
is_delete_all = False
|
|
|
|
|
|
|
|
|
|
|
|
if want_continue:
|
|
|
|
|
|
lst_want_continue = [
|
|
|
|
|
|
a.strip() for a in want_continue.split(",")
|
|
|
|
|
|
]
|
|
|
|
|
|
if "a" in lst_want_continue:
|
|
|
|
|
|
is_delete_all = True
|
|
|
|
|
|
lst_module_to_delete = [
|
|
|
|
|
|
lst_module_missing_next_version[a]
|
|
|
|
|
|
for a in range(
|
|
|
|
|
|
len(lst_module_missing_next_version)
|
|
|
|
|
|
)
|
|
|
|
|
|
]
|
|
|
|
|
|
else:
|
|
|
|
|
|
# TODO show error if the index is wrong
|
|
|
|
|
|
lst_want_continue_number = [
|
|
|
|
|
|
int(a)
|
|
|
|
|
|
for a in lst_want_continue
|
|
|
|
|
|
if a.isdigit()
|
|
|
|
|
|
]
|
|
|
|
|
|
lst_module_to_delete = [
|
|
|
|
|
|
lst_module_missing_next_version[a]
|
|
|
|
|
|
for a in lst_want_continue_number
|
|
|
|
|
|
if 0
|
|
|
|
|
|
<= a
|
|
|
|
|
|
< len(lst_module_missing_next_version)
|
|
|
|
|
|
]
|
|
|
|
|
|
if len(lst_module_to_delete) == len(
|
|
|
|
|
|
lst_module_missing_next_version
|
|
|
|
|
|
):
|
|
|
|
|
|
is_delete_all = True
|
|
|
|
|
|
|
|
|
|
|
|
if next_version == 15:
|
|
|
|
|
|
lst_module_to_delete.append("users_default_groups")
|
|
|
|
|
|
lst_module_to_delete.append(
|
|
|
|
|
|
"web_editor_backend_context"
|
|
|
|
|
|
)
|
|
|
|
|
|
lst_module_to_delete.append(
|
|
|
|
|
|
"website_google_analytics_fixed"
|
|
|
|
|
|
)
|
|
|
|
|
|
elif next_version == 17:
|
|
|
|
|
|
lst_module_to_delete.append(
|
|
|
|
|
|
"export_delete_login_log"
|
|
|
|
|
|
)
|
|
|
|
|
|
elif next_version == 18:
|
|
|
|
|
|
lst_module_to_delete.append(
|
|
|
|
|
|
"base_attachment_object_storage"
|
|
|
|
|
|
)
|
|
|
|
|
|
lst_module_to_delete.append(
|
|
|
|
|
|
"user_password_strength"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if "e" in lst_want_continue:
|
|
|
|
|
|
want_continue = (
|
|
|
|
|
|
input(
|
|
|
|
|
|
f"💬 Enumerate module name to delete, separate by coma : "
|
|
|
|
|
|
)
|
|
|
|
|
|
.strip()
|
|
|
|
|
|
.lower()
|
|
|
|
|
|
)
|
|
|
|
|
|
lst_to_extend = [
|
|
|
|
|
|
a.strip() for a in want_continue.split(",")
|
|
|
|
|
|
]
|
|
|
|
|
|
lst_module_to_delete.extend(lst_to_extend)
|
|
|
|
|
|
|
|
|
|
|
|
if lst_module_to_delete:
|
|
|
|
|
|
msg = f"4.{index}.{chr(option_comment + 65)}.option - Choose delete missing module"
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
self.switch_odoo(next_version - 1)
|
|
|
|
|
|
|
|
|
|
|
|
if lst_module_to_delete:
|
|
|
|
|
|
# Delete if exist database
|
|
|
|
|
|
self.todo_upgrade_execute(
|
|
|
|
|
|
f"./script/database/db_restore.py -d {database_name_upgrade} --only_drop",
|
|
|
|
|
|
)
|
|
|
|
|
|
# Duplicate database
|
|
|
|
|
|
cmd_clone_database = f"./odoo_bin.sh db --clone --from_database {last_database_name} --database {database_name_upgrade}"
|
|
|
|
|
|
self.todo_upgrade_execute(cmd_clone_database)
|
|
|
|
|
|
self.uninstall_from_database(
|
|
|
|
|
|
lst_module_to_delete,
|
|
|
|
|
|
database_name_upgrade,
|
|
|
|
|
|
next_version,
|
|
|
|
|
|
)
|
|
|
|
|
|
self.install_from_database(
|
|
|
|
|
|
lst_module_to_install,
|
|
|
|
|
|
database_name_upgrade,
|
|
|
|
|
|
next_version - 1,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if not is_delete_all:
|
|
|
|
|
|
msg = f"4.{index}.{chr(option_comment + 65)}.option - Choose auto-fix (not implemented yet)"
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
lst_module_to_migrate_code = set(
|
|
|
|
|
|
lst_module_missing_next_version
|
|
|
|
|
|
) - set(lst_module_to_delete)
|
|
|
|
|
|
(
|
|
|
|
|
|
lst_module_missing_last,
|
|
|
|
|
|
lst_module_duplicate_last,
|
|
|
|
|
|
lst_module_exist_last,
|
|
|
|
|
|
lst_module_error_last,
|
|
|
|
|
|
) = self.check_addons_exist(
|
|
|
|
|
|
lst_module_to_migrate_code, get_all_info=True
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if lst_module_missing_last:
|
|
|
|
|
|
print(
|
|
|
|
|
|
f"Error missing module : {lst_module_missing_last}"
|
|
|
|
|
|
)
|
|
|
|
|
|
if lst_module_duplicate_last:
|
|
|
|
|
|
print(
|
|
|
|
|
|
f"Error duplicate module : {lst_module_duplicate_last}"
|
|
|
|
|
|
)
|
|
|
|
|
|
if lst_module_error_last:
|
|
|
|
|
|
print(
|
|
|
|
|
|
f"Error error module : {lst_module_error_last}"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if lst_module_exist_last:
|
|
|
|
|
|
odoo_name_last_version = (
|
|
|
|
|
|
f"odoo{next_version - 1}.0"
|
|
|
|
|
|
)
|
|
|
|
|
|
odoo_name_actual_version = f"odoo{next_version}.0"
|
|
|
|
|
|
for (
|
|
|
|
|
|
module_name,
|
|
|
|
|
|
module_path,
|
|
|
|
|
|
) in lst_module_exist_last:
|
|
|
|
|
|
module_dir_path = os.path.dirname(module_path)
|
|
|
|
|
|
module_dir_path_new_version = (
|
|
|
|
|
|
module_dir_path.replace(
|
|
|
|
|
|
odoo_name_last_version,
|
|
|
|
|
|
odoo_name_actual_version,
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
module_dir_path_manifest = os.path.join(
|
|
|
|
|
|
module_path, "__manifest__.py"
|
|
|
|
|
|
)
|
|
|
|
|
|
module_dir_new_version = os.path.join(
|
|
|
|
|
|
module_dir_path_new_version, module_name
|
|
|
|
|
|
)
|
|
|
|
|
|
module_dir_new_version_manifest = os.path.join(
|
|
|
|
|
|
module_dir_new_version, "__manifest__.py"
|
|
|
|
|
|
)
|
|
|
|
|
|
dct_module_to_migrate_module = {
|
|
|
|
|
|
"source_module_path": module_path,
|
|
|
|
|
|
"source_manifest_path": module_dir_path_manifest,
|
|
|
|
|
|
"source_addons_path": module_dir_path,
|
|
|
|
|
|
"target_module_path": module_dir_new_version,
|
|
|
|
|
|
"target_manifest_path": module_dir_new_version_manifest,
|
|
|
|
|
|
"target_addons_path": module_dir_path_new_version,
|
|
|
|
|
|
"module_name": module_name,
|
|
|
|
|
|
"source_version_odoo": next_version - 1,
|
|
|
|
|
|
"target_version_odoo": next_version,
|
|
|
|
|
|
}
|
|
|
|
|
|
# TODO move this into config
|
|
|
|
|
|
lst_module_to_migrate.append(
|
|
|
|
|
|
dct_module_to_migrate_module
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
self.dct_progression[
|
|
|
|
|
|
"config_state_4_module_to_migrate_code"
|
|
|
|
|
|
][index] = lst_module_to_migrate
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
self.switch_odoo(next_version)
|
|
|
|
|
|
# TODO auto-fix
|
|
|
|
|
|
# TODO try to migrate module, find in previous version, application la migration vers une nouvelle version
|
|
|
|
|
|
# TODO ajouté menu todo qui permet de faire une migration d'un module et migrer le générateur de code.
|
|
|
|
|
|
# TODO when check module, reminder provenance
|
|
|
|
|
|
# TODO implement asyncio instead of parallel
|
|
|
|
|
|
# TODO detect when duplicate path module ou module manquant, prendre décision qui ont efface si dupliqué
|
|
|
|
|
|
# TODO pourquoi web_ir_actions_act_multi est doublé dans odoo 13
|
|
|
|
|
|
|
|
|
|
|
|
lst_module_search_missing_module[index] = True
|
|
|
|
|
|
self.dct_progression["state_4_search_missing_module"] = (
|
|
|
|
|
|
lst_module_search_missing_module
|
|
|
|
|
|
)
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
option_comment += 1
|
|
|
|
|
|
msg = f"4.{index}.{chr(option_comment + 65)} - Migrate module"
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
lst_path_git_clone_migrate = []
|
|
|
|
|
|
|
|
|
|
|
|
if not lst_module_migrate_odoo[index]:
|
|
|
|
|
|
# TODO Searching module
|
|
|
|
|
|
# search addons/addons
|
|
|
|
|
|
# search read manifest and detect branch difference, manifest into private?
|
|
|
|
|
|
# Extract module name and run migration to another list
|
|
|
|
|
|
# Maybe check if already exist and show list or continue with overwrite
|
|
|
|
|
|
# Expliquer pourquoi on ne fait pas le oca-port, c'est
|
|
|
|
|
|
|
|
|
|
|
|
config_migrate_repo = self.dct_progression.get(
|
|
|
|
|
|
"config_migrate_repo", False
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_progression["config_migrate_repo"] = (
|
|
|
|
|
|
config_migrate_repo
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if config_migrate_repo:
|
|
|
|
|
|
dct_module_result = self.search_module_to_move(
|
|
|
|
|
|
next_version - 1, next_version
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# TODO code migration
|
|
|
|
|
|
# git stash
|
|
|
|
|
|
# call odoo-module-migrate, without commit
|
|
|
|
|
|
|
|
|
|
|
|
source_module_path = dct_module_result.get(
|
|
|
|
|
|
"source_module_path"
|
|
|
|
|
|
)
|
|
|
|
|
|
if not source_module_path:
|
|
|
|
|
|
_logger.error(
|
|
|
|
|
|
f"Missing source module path '{source_module_path}'"
|
|
|
|
|
|
)
|
|
|
|
|
|
else:
|
|
|
|
|
|
if os.path.exists(
|
|
|
|
|
|
os.path.join(source_module_path, ".git")
|
|
|
|
|
|
):
|
|
|
|
|
|
self.todo_upgrade_execute(
|
|
|
|
|
|
f"cd '{source_module_path}' && git stash && cd ~-"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
target_module_path = dct_module_result.get(
|
|
|
|
|
|
"target_module_path"
|
|
|
|
|
|
)
|
|
|
|
|
|
if not target_module_path:
|
|
|
|
|
|
_logger.error(
|
|
|
|
|
|
f"Missing target module path '{target_module_path}'"
|
|
|
|
|
|
)
|
|
|
|
|
|
else:
|
|
|
|
|
|
if os.path.exists(
|
|
|
|
|
|
os.path.join(target_module_path, ".git")
|
|
|
|
|
|
):
|
|
|
|
|
|
self.todo_upgrade_execute(
|
|
|
|
|
|
f"cd '{target_module_path}' && git stash && cd ~-"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
lst_module_to_migrate_all = dct_module_result.get(
|
|
|
|
|
|
"lst_module", []
|
|
|
|
|
|
)
|
|
|
|
|
|
else:
|
|
|
|
|
|
lst_module_to_migrate_all = []
|
|
|
|
|
|
|
|
|
|
|
|
# TODO remove duplicate au lieu d'extend
|
|
|
|
|
|
lst_module_to_migrate_all.extend(lst_module_to_migrate)
|
|
|
|
|
|
|
|
|
|
|
|
self.internal_module_upgrade(
|
|
|
|
|
|
next_version,
|
|
|
|
|
|
lst_module_to_migrate_all,
|
|
|
|
|
|
lst_path_git_clone_migrate,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
lst_module_migrate_odoo[index] = True
|
|
|
|
|
|
self.dct_progression["state_4_module_migrate_odoo_lst"] = (
|
|
|
|
|
|
lst_module_migrate_odoo
|
|
|
|
|
|
)
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
print(f"✅ -> Module upgrade Odoo{next_version} done")
|
|
|
|
|
|
else:
|
|
|
|
|
|
print(f"✅ -> Module upgrade Odoo{next_version} - nothing")
|
|
|
|
|
|
|
|
|
|
|
|
option_comment += 1
|
|
|
|
|
|
msg = f"4.{index}.{chr(option_comment + 65)} - Fix migrate code"
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
if not lst_fix_migration_odoo[index]:
|
|
|
|
|
|
print("")
|
|
|
|
|
|
file_path_fix_migration = os.path.join(
|
|
|
|
|
|
"script",
|
|
|
|
|
|
"odoo",
|
|
|
|
|
|
"migration",
|
|
|
|
|
|
f"fix_migration_odoo{(next_version-1)*10}_to_odoo{next_version*10}.py",
|
|
|
|
|
|
)
|
|
|
|
|
|
if os.path.exists(file_path_fix_migration):
|
|
|
|
|
|
self.todo_upgrade_execute(
|
|
|
|
|
|
f"cat ./{file_path_fix_migration} | ./odoo{next_version}.0/odoo/odoo-bin shell -d {database_name_upgrade}",
|
|
|
|
|
|
single_source_odoo=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
lst_fix_migration_odoo[index] = file_path_fix_migration
|
|
|
|
|
|
self.dct_progression["state_4_fix_migration_odoo_lst"] = (
|
|
|
|
|
|
lst_fix_migration_odoo
|
|
|
|
|
|
)
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
print(f"✅ -> Fix migration Odoo{next_version} done")
|
|
|
|
|
|
else:
|
|
|
|
|
|
print(
|
|
|
|
|
|
f"✅ -> Fix migration Odoo{next_version} - no fix to execute"
|
|
|
|
|
|
)
|
|
|
|
|
|
else:
|
|
|
|
|
|
print(f"✅ -> Fix migration Odoo{next_version} - nothing")
|
|
|
|
|
|
|
|
|
|
|
|
for path_git_clone_migrate in lst_path_git_clone_migrate:
|
|
|
|
|
|
cmd = f"./script/code/git_commit_migration_addons_path.py --path {path_git_clone_migrate} --odoo_version {next_version}.0"
|
|
|
|
|
|
self.todo_upgrade_execute(cmd)
|
|
|
|
|
|
|
|
|
|
|
|
option_comment += 1
|
|
|
|
|
|
msg = f"4.{index}.{chr(option_comment + 65)} - Migrate database"
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
if not lst_upgrade_odoo[index]:
|
|
|
|
|
|
path_addons_openupgrade = os.path.join(
|
|
|
|
|
|
os.getcwd(), f"odoo{next_version}.0", "OCA_OpenUpgrade"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# Update config with OCA_OpenUpgrade
|
|
|
|
|
|
ignore_path = (
|
|
|
|
|
|
"--ignore-odoo-path " if next_version <= 13 else ""
|
|
|
|
|
|
)
|
|
|
|
|
|
extra_addons_path_extra = (
|
|
|
|
|
|
f",{path_addons_openupgrade}/addons,{path_addons_openupgrade}/odoo/addons"
|
|
|
|
|
|
if next_version <= 13
|
|
|
|
|
|
else ""
|
|
|
|
|
|
)
|
|
|
|
|
|
cmd_update_config = (
|
|
|
|
|
|
f"./script/git/git_repo_update_group.py {ignore_path}"
|
|
|
|
|
|
f"--extra-addons-path {path_addons_openupgrade}{extra_addons_path_extra} "
|
|
|
|
|
|
f"&& ./script/generate_config.sh"
|
|
|
|
|
|
)
|
|
|
|
|
|
self.todo_upgrade_execute(cmd_update_config)
|
|
|
|
|
|
|
|
|
|
|
|
print("🚸 Please, validate commits after code migration.")
|
|
|
|
|
|
print("ℹ To show repo status :\nmake repo_show_status")
|
|
|
|
|
|
print(
|
|
|
|
|
|
f"🚸 Please, validate this path into config.conf : '{path_addons_openupgrade}'."
|
|
|
|
|
|
)
|
|
|
|
|
|
status = input(f"💬 Press to continue {msg} : ").strip()
|
|
|
|
|
|
# The technique change at version 14
|
|
|
|
|
|
if next_version <= 13:
|
|
|
|
|
|
erplibre_version = self.install_OCA_openupgrade(
|
|
|
|
|
|
next_version
|
|
|
|
|
|
)
|
|
|
|
|
|
cmd_upgrade = f".venv.{erplibre_version}/bin/python ./odoo{next_version}.0/OCA_OpenUpgrade/odoo-bin -c ./config.conf --update all --no-http --stop-after-init -d {database_name_upgrade}"
|
|
|
|
|
|
else:
|
|
|
|
|
|
cmd_upgrade = f"./run.sh --upgrade-path=./odoo{next_version}.0/OCA_OpenUpgrade/openupgrade_scripts/scripts --update all -c config.conf --stop-after-init --no-http --load=base,web,openupgrade_framework -d {database_name_upgrade}"
|
|
|
|
|
|
lst_upgrade_odoo[index] = cmd_upgrade
|
|
|
|
|
|
|
|
|
|
|
|
self.todo_upgrade_execute(
|
|
|
|
|
|
cmd_upgrade,
|
|
|
|
|
|
new_env={
|
|
|
|
|
|
"OPENUPGRADE_TARGET_VERSION": f"{next_version}.0"
|
|
|
|
|
|
},
|
|
|
|
|
|
)
|
|
|
|
|
|
# TODO detect error
|
|
|
|
|
|
|
|
|
|
|
|
self.dct_progression["state_4_upgrade_odoo_lst"] = (
|
|
|
|
|
|
lst_upgrade_odoo
|
|
|
|
|
|
)
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
str_wait_next_version = (
|
|
|
|
|
|
" (or wait next version 🤖)"
|
|
|
|
|
|
if next_version != lst_next_version[-1]
|
|
|
|
|
|
else ""
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
status = (
|
|
|
|
|
|
input(
|
|
|
|
|
|
f"💬 Do you want to upgrade all{str_wait_next_version}? Press y/Y to upgrade all addons database : "
|
|
|
|
|
|
)
|
|
|
|
|
|
.strip()
|
|
|
|
|
|
.lower()
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if status == "y":
|
|
|
|
|
|
self.todo_upgrade_execute(
|
|
|
|
|
|
f"./script/addons/update_addons_all.sh {database_name_upgrade}",
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
print(f"✅ -> Database upgrade Odoo{next_version} done")
|
|
|
|
|
|
|
|
|
|
|
|
# Update config without OCA_OpenUpgrade
|
|
|
|
|
|
cmd_update_config = f"./script/git/git_repo_update_group.py && ./script/generate_config.sh"
|
|
|
|
|
|
self.todo_upgrade_execute(cmd_update_config)
|
|
|
|
|
|
print("[y] Open server with Selenium")
|
|
|
|
|
|
status = (
|
|
|
|
|
|
input(
|
|
|
|
|
|
"💬 Do you want to test this upgrade? Choose or press to ignore it : "
|
|
|
|
|
|
)
|
|
|
|
|
|
.strip()
|
|
|
|
|
|
.lower()
|
|
|
|
|
|
)
|
|
|
|
|
|
"make repo_show_status"
|
|
|
|
|
|
if status == "y":
|
|
|
|
|
|
self.todo.prompt_execute_selenium_and_run_db(
|
|
|
|
|
|
database_name_upgrade
|
|
|
|
|
|
)
|
|
|
|
|
|
status = input(
|
|
|
|
|
|
f"💬 Press to continue 4.{index} : "
|
|
|
|
|
|
).strip()
|
|
|
|
|
|
else:
|
|
|
|
|
|
print(f"✅ -> Database upgrade Odoo{next_version} - nothing")
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
# waiting_input = input("💬 Press any keyboard key to continue...")
|
|
|
|
|
|
print("")
|
|
|
|
|
|
|
|
|
|
|
|
msg = "5 - Cleaning up database after upgrade"
|
|
|
|
|
|
print(f"🔷 {msg}")
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
print(
|
|
|
|
|
|
"✨ Re-update i18n, purger data, tables (except mail_test and mail_test_full)"
|
|
|
|
|
|
)
|
|
|
|
|
|
# waiting_input = input("💬print Press any keyboard key to continue...")
|
|
|
|
|
|
msg = "6 - Migration finished"
|
|
|
|
|
|
print(f"🔷 {msg}")
|
|
|
|
|
|
self.add_comment_progression(msg)
|
|
|
|
|
|
|
|
|
|
|
|
cmd_backup_template = f"./odoo_bin.sh db --backup --database {database_name_upgrade} --restore_image"
|
|
|
|
|
|
cmd_backup = f"{cmd_backup_template} {database_name_upgrade}_finish_{datetime.datetime.now().strftime('%Y%m%d%H%M%S')}"
|
|
|
|
|
|
print(f"✨ Can execute backup creation :\n{cmd_backup}")
|
|
|
|
|
|
status = input(
|
|
|
|
|
|
"💬 Press y/Y or write filename.zip to export or enter to continue : "
|
|
|
|
|
|
).strip()
|
|
|
|
|
|
if status.lower():
|
|
|
|
|
|
if status.lower() != "y":
|
|
|
|
|
|
cmd_backup = f"{cmd_backup_template} {status}"
|
|
|
|
|
|
self.todo_upgrade_execute(cmd_backup)
|
|
|
|
|
|
|
|
|
|
|
|
status = input("💬 Test the migration, press y/Y : ")
|
|
|
|
|
|
if status.lower().strip() == "y":
|
|
|
|
|
|
self.todo.prompt_execute_selenium_and_run_db(database_name_upgrade)
|
|
|
|
|
|
|
|
|
|
|
|
def get_rename_module(self, lst_module, next_version):
|
|
|
|
|
|
path_search = f"odoo{next_version}.0/OCA_OpenUpgrade/"
|
|
|
|
|
|
status, cmd_executed, lst_output = self.todo_upgrade_execute(
|
|
|
|
|
|
f"find {path_search} -name apriori.py",
|
|
|
|
|
|
get_output=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if not lst_output:
|
|
|
|
|
|
_logger.error(
|
|
|
|
|
|
f"Cannot find renamed module script apriori.py into path '{path_search}'"
|
|
|
|
|
|
)
|
|
|
|
|
|
return lst_module
|
|
|
|
|
|
apriory_py = lst_output[0].strip()
|
|
|
|
|
|
|
|
|
|
|
|
with open(apriory_py, "r") as f:
|
|
|
|
|
|
file_content = f.read()
|
|
|
|
|
|
|
|
|
|
|
|
data_vars = {}
|
|
|
|
|
|
exec(file_content, data_vars)
|
|
|
|
|
|
renamed_modules = data_vars.get("renamed_modules", {})
|
|
|
|
|
|
merged_modules = data_vars.get("merged_modules", {})
|
|
|
|
|
|
deleted_modules = data_vars.get("deleted_modules", [])
|
|
|
|
|
|
|
|
|
|
|
|
lst_index_to_delete = []
|
|
|
|
|
|
for index, module in enumerate(lst_module):
|
|
|
|
|
|
renamed_module = renamed_modules.get(module)
|
|
|
|
|
|
merged_module = merged_modules.get(module)
|
|
|
|
|
|
if renamed_module:
|
|
|
|
|
|
lst_module[index] = renamed_module
|
|
|
|
|
|
if merged_module:
|
|
|
|
|
|
lst_module[index] = merged_module
|
|
|
|
|
|
if module in deleted_modules:
|
|
|
|
|
|
lst_index_to_delete.append(index)
|
|
|
|
|
|
for index_to_delete in lst_index_to_delete[::-1]:
|
|
|
|
|
|
lst_module.pop(index_to_delete)
|
|
|
|
|
|
return list(set(lst_module))
|
|
|
|
|
|
|
|
|
|
|
|
def search_module_to_move(self, source_version_odoo, target_version_odoo):
|
|
|
|
|
|
lst_module = []
|
|
|
|
|
|
# lst_path_to_check = [
|
|
|
|
|
|
# os.path.join(f"odoo{actual_version_odoo}", "addons"),
|
|
|
|
|
|
# os.path.join(f"odoo{target_version_odoo}", "addons"),
|
|
|
|
|
|
# os.path.join(f"private", "addons"),
|
|
|
|
|
|
# ]
|
|
|
|
|
|
source_path_to_check = os.path.join(
|
|
|
|
|
|
f"odoo{source_version_odoo}.0", "addons", "addons"
|
|
|
|
|
|
)
|
|
|
|
|
|
target_path_to_check = os.path.join(
|
|
|
|
|
|
f"odoo{target_version_odoo}.0", "addons", "addons"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# Search
|
|
|
|
|
|
is_moving_git = False
|
|
|
|
|
|
if os.path.exists(source_path_to_check):
|
|
|
|
|
|
if os.path.exists(os.path.join(source_path_to_check, ".git")):
|
|
|
|
|
|
is_moving_git = True
|
|
|
|
|
|
if not os.path.exists(target_path_to_check):
|
|
|
|
|
|
shutil.copytree(source_path_to_check, target_path_to_check)
|
|
|
|
|
|
# if not is_moving_git:
|
|
|
|
|
|
# os.mkdir(path_to_check_target)
|
|
|
|
|
|
# else:
|
|
|
|
|
|
# # TODO clone
|
|
|
|
|
|
# pass
|
|
|
|
|
|
|
|
|
|
|
|
if not is_moving_git:
|
|
|
|
|
|
# TODO do something
|
|
|
|
|
|
# Time to compare
|
|
|
|
|
|
os.listdir(source_path_to_check)
|
|
|
|
|
|
|
|
|
|
|
|
if os.path.exists(target_path_to_check):
|
|
|
|
|
|
for dir_name in os.listdir(target_path_to_check):
|
|
|
|
|
|
source_module_path = os.path.join(
|
|
|
|
|
|
source_path_to_check, dir_name
|
|
|
|
|
|
)
|
|
|
|
|
|
source_manifest_path = os.path.join(
|
|
|
|
|
|
source_module_path, "__manifest__.py"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
target_module_path = os.path.join(
|
|
|
|
|
|
target_path_to_check, dir_name
|
|
|
|
|
|
)
|
|
|
|
|
|
target_manifest_path = os.path.join(
|
|
|
|
|
|
target_module_path, "__manifest__.py"
|
|
|
|
|
|
)
|
|
|
|
|
|
if os.path.exists(target_manifest_path):
|
|
|
|
|
|
# TODO remove from list when module already exist in version 15
|
|
|
|
|
|
dct_module = {
|
|
|
|
|
|
"source_module_path": source_module_path,
|
|
|
|
|
|
"source_manifest_path": source_manifest_path,
|
|
|
|
|
|
"source_addons_path": source_path_to_check,
|
|
|
|
|
|
"target_module_path": target_module_path,
|
|
|
|
|
|
"target_manifest_path": target_manifest_path,
|
|
|
|
|
|
"target_addons_path": target_path_to_check,
|
|
|
|
|
|
"module_name": dir_name,
|
|
|
|
|
|
"source_version_odoo": source_version_odoo,
|
|
|
|
|
|
"target_version_odoo": target_version_odoo,
|
|
|
|
|
|
}
|
|
|
|
|
|
lst_module.append(dct_module)
|
|
|
|
|
|
|
|
|
|
|
|
dct_module = {
|
|
|
|
|
|
"lst_module": lst_module,
|
|
|
|
|
|
"source_module_path": source_path_to_check,
|
|
|
|
|
|
"target_module_path": target_path_to_check,
|
|
|
|
|
|
}
|
|
|
|
|
|
return dct_module
|
|
|
|
|
|
|
|
|
|
|
|
def uninstall_from_database(
|
|
|
|
|
|
self, lst_module_to_uninstall, database_name, actual_version
|
|
|
|
|
|
):
|
|
|
|
|
|
if not lst_module_to_uninstall:
|
|
|
|
|
|
return
|
|
|
|
|
|
uninstall_module = ",".join(lst_module_to_uninstall)
|
|
|
|
|
|
self.todo_upgrade_execute(
|
|
|
|
|
|
f"./script/addons/uninstall_addons.sh {database_name} {uninstall_module}",
|
|
|
|
|
|
single_source_odoo=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# Update list installed module
|
|
|
|
|
|
self.dct_module_per_version[actual_version] = sorted(
|
|
|
|
|
|
list(
|
|
|
|
|
|
set(self.dct_module_per_version[actual_version])
|
|
|
|
|
|
- set(lst_module_to_uninstall)
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_progression["dct_module_per_version"] = (
|
|
|
|
|
|
self.dct_module_per_version
|
|
|
|
|
|
)
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
def install_from_database(
|
|
|
|
|
|
self, lst_module_to_install, database_name, actual_version
|
|
|
|
|
|
):
|
|
|
|
|
|
if not lst_module_to_install:
|
|
|
|
|
|
return
|
|
|
|
|
|
install_module = ",".join(lst_module_to_install)
|
|
|
|
|
|
self.todo_upgrade_execute(
|
|
|
|
|
|
f"./script/addons/install_addons.sh {database_name} {install_module}",
|
|
|
|
|
|
single_source_odoo=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# Update list installed module
|
|
|
|
|
|
self.dct_module_per_version[actual_version] = sorted(
|
|
|
|
|
|
list(
|
|
|
|
|
|
set(
|
|
|
|
|
|
self.dct_module_per_version[actual_version]
|
|
|
|
|
|
+ lst_module_to_install
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
self.dct_progression["dct_module_per_version"] = (
|
|
|
|
|
|
self.dct_module_per_version
|
|
|
|
|
|
)
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
|
|
|
|
|
|
def check_addons_exist(
|
|
|
|
|
|
self, lst_module_to_check, ignore_error=True, get_all_info=False
|
|
|
|
|
|
):
|
|
|
|
|
|
str_module_to_check = ",".join(sorted(lst_module_to_check))
|
|
|
|
|
|
status, cmd_executed, dct_output = self.todo_upgrade_execute(
|
|
|
|
|
|
f"{PYTHON_BIN} ./script/addons/check_addons_exist.py --format_json --output_json -m {str_module_to_check}",
|
|
|
|
|
|
get_output=True,
|
|
|
|
|
|
output_is_json=True,
|
|
|
|
|
|
wait_at_error=not ignore_error,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
lst_module_missing = dct_output.get("missing")
|
|
|
|
|
|
lst_module_duplicate = dct_output.get("duplicate")
|
|
|
|
|
|
if get_all_info:
|
|
|
|
|
|
lst_module_error = dct_output.get("error")
|
|
|
|
|
|
lst_module_exist = dct_output.get("exist")
|
|
|
|
|
|
return (
|
|
|
|
|
|
lst_module_missing,
|
|
|
|
|
|
lst_module_duplicate,
|
|
|
|
|
|
lst_module_exist,
|
|
|
|
|
|
lst_module_error,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
return lst_module_missing, lst_module_duplicate
|
|
|
|
|
|
|
|
|
|
|
|
def switch_odoo(self, odoo_version):
|
|
|
|
|
|
int_odoo_version = int(float(odoo_version))
|
|
|
|
|
|
|
|
|
|
|
|
# Expect odoo_version like 12.0
|
|
|
|
|
|
lst_version, lst_version_installed, odoo_installed_version = (
|
2026-03-26 15:45:44 -04:00
|
|
|
|
get_odoo_version()
|
2025-10-31 01:10:54 -04:00
|
|
|
|
)
|
|
|
|
|
|
if odoo_installed_version != f"odoo{int_odoo_version}.0":
|
|
|
|
|
|
print(
|
|
|
|
|
|
f"⧖ -> Was '{odoo_installed_version}', Switch to odoo{int_odoo_version}.0"
|
|
|
|
|
|
)
|
|
|
|
|
|
self.todo_upgrade_execute(f"make switch_odoo_{int_odoo_version}")
|
|
|
|
|
|
self.todo_upgrade_execute("make config_gen_all")
|
|
|
|
|
|
|
|
|
|
|
|
def install_OCA_odoo_module_migrator(self):
|
|
|
|
|
|
if not os.path.exists(PATH_VENV_MODULE_MIGRATOR):
|
|
|
|
|
|
self.todo_upgrade_execute(
|
|
|
|
|
|
f"cd {PATH_OCA_ODOO_MODULE_MIGRATOR} && python -m venv {VENV_NAME_MODULE_MIGRATOR} && source {VENV_NAME_MODULE_MIGRATOR}/bin/activate && pip3 install -r requirements.txt"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def install_OCA_openupgrade(self, next_version):
|
|
|
|
|
|
# TODO install odoorpc==0.7.0
|
|
|
|
|
|
# openupgradelib
|
|
|
|
|
|
# openupgrade_path = f"odoo{next_version}.0/OCA_OpenUpgrade"
|
|
|
|
|
|
# venv_oca_path = f"{openupgrade_path}/.venv"
|
|
|
|
|
|
# if os.path.exists(venv_oca_path):
|
|
|
|
|
|
# return
|
|
|
|
|
|
lst_version, lst_version_installed, odoo_installed_version = (
|
2026-03-26 15:45:44 -04:00
|
|
|
|
get_odoo_version()
|
2025-10-31 01:10:54 -04:00
|
|
|
|
)
|
|
|
|
|
|
extract_version = f"{next_version}.0"
|
|
|
|
|
|
dct_erplibre_info = [
|
|
|
|
|
|
a for a in lst_version if a.get("odoo_version") == extract_version
|
|
|
|
|
|
]
|
|
|
|
|
|
if not dct_erplibre_info:
|
|
|
|
|
|
raise Exception(f"Cannot extract {extract_version}")
|
|
|
|
|
|
dct_erplibre_info = dct_erplibre_info[0]
|
|
|
|
|
|
erplibre_version = dct_erplibre_info.get("erplibre_version")
|
|
|
|
|
|
# self.todo_upgrade_execute(
|
|
|
|
|
|
# f".venv.{erplibre_version}/bin/python -m venv {venv_oca_path} && {venv_oca_path}/bin/pip3 install -r {openupgrade_path}/requirements.txt"
|
|
|
|
|
|
# )
|
|
|
|
|
|
self.todo_upgrade_execute(
|
|
|
|
|
|
f".venv.{erplibre_version}/bin/pip install odoorpc==0.7.0"
|
|
|
|
|
|
)
|
|
|
|
|
|
self.todo_upgrade_execute(
|
|
|
|
|
|
f".venv.{erplibre_version}/bin/pip install openupgradelib"
|
|
|
|
|
|
)
|
|
|
|
|
|
return erplibre_version
|
|
|
|
|
|
|
|
|
|
|
|
def todo_upgrade_execute(
|
|
|
|
|
|
self,
|
|
|
|
|
|
cmd,
|
|
|
|
|
|
single_source_odoo=False,
|
|
|
|
|
|
new_env=None,
|
|
|
|
|
|
quiet=False,
|
|
|
|
|
|
get_output=False,
|
|
|
|
|
|
output_is_json=False,
|
|
|
|
|
|
wait_at_error=True,
|
|
|
|
|
|
):
|
|
|
|
|
|
if output_is_json and not get_output:
|
|
|
|
|
|
get_output = True
|
|
|
|
|
|
output = None
|
|
|
|
|
|
if get_output:
|
2026-02-13 01:27:38 -05:00
|
|
|
|
status, cmd_executed, output = self.execute.exec_command_live(
|
2025-10-31 01:10:54 -04:00
|
|
|
|
cmd,
|
|
|
|
|
|
source_erplibre=False,
|
|
|
|
|
|
single_source_odoo=single_source_odoo,
|
|
|
|
|
|
new_env=new_env,
|
|
|
|
|
|
return_status_and_output_and_command=True,
|
|
|
|
|
|
quiet=quiet,
|
|
|
|
|
|
)
|
|
|
|
|
|
else:
|
2026-02-13 01:27:38 -05:00
|
|
|
|
status, cmd_executed = self.execute.exec_command_live(
|
2025-10-31 01:10:54 -04:00
|
|
|
|
cmd,
|
|
|
|
|
|
source_erplibre=False,
|
|
|
|
|
|
single_source_odoo=single_source_odoo,
|
|
|
|
|
|
new_env=new_env,
|
|
|
|
|
|
return_status_and_command=True,
|
|
|
|
|
|
quiet=quiet,
|
|
|
|
|
|
)
|
|
|
|
|
|
self.lst_command_executed.append(cmd_executed)
|
|
|
|
|
|
self.dct_progression["command_executed"] = self.lst_command_executed
|
|
|
|
|
|
self.write_config()
|
|
|
|
|
|
if status and wait_at_error:
|
|
|
|
|
|
print("[1] to redo the command")
|
|
|
|
|
|
wait_status = (
|
|
|
|
|
|
input(
|
|
|
|
|
|
"💬 Error detected, press to continue or ctrl+c to stop : "
|
|
|
|
|
|
)
|
|
|
|
|
|
.strip()
|
|
|
|
|
|
.lower()
|
|
|
|
|
|
)
|
2026-02-22 12:14:07 -05:00
|
|
|
|
|
|
|
|
|
|
# psycopg2.errors.UndefinedTable: relation "discuss_channel" does not exist
|
|
|
|
|
|
# LIGNE 1 : SELECT "discuss_channel"."id" FROM "discuss_channel" WHERE (...
|
|
|
|
|
|
|
2025-10-31 01:10:54 -04:00
|
|
|
|
if wait_status == "1":
|
|
|
|
|
|
return self.todo_upgrade_execute(
|
|
|
|
|
|
cmd,
|
|
|
|
|
|
single_source_odoo=single_source_odoo,
|
|
|
|
|
|
new_env=new_env,
|
|
|
|
|
|
quiet=quiet,
|
|
|
|
|
|
get_output=get_output,
|
|
|
|
|
|
output_is_json=output_is_json,
|
|
|
|
|
|
wait_at_error=wait_at_error,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if get_output:
|
|
|
|
|
|
if output_is_json:
|
|
|
|
|
|
str_output = json.loads("".join(output))
|
|
|
|
|
|
return status, cmd_executed, str_output
|
|
|
|
|
|
return status, cmd_executed, output
|
|
|
|
|
|
return status, cmd_executed
|
|
|
|
|
|
|
|
|
|
|
|
def check_and_clone_source_to_target_migration_code(
|
|
|
|
|
|
self, next_version, source_addons_path, target_addons_path
|
|
|
|
|
|
):
|
|
|
|
|
|
if not os.path.exists(os.path.join(source_addons_path, ".git")):
|
|
|
|
|
|
return
|
|
|
|
|
|
if os.path.exists(os.path.join(target_addons_path, ".git")):
|
|
|
|
|
|
return
|
|
|
|
|
|
# if not os.path.exists(target_addons_path):
|
|
|
|
|
|
# cmd_mkdir = f"mkdir -p {target_addons_path}"
|
|
|
|
|
|
# status, cmd_executed, lst_output = self.todo_upgrade_execute(
|
|
|
|
|
|
# cmd_mkdir,
|
|
|
|
|
|
# get_output=True,
|
|
|
|
|
|
# )
|
|
|
|
|
|
# return
|
|
|
|
|
|
source_dir_name = os.path.basename(source_addons_path)
|
|
|
|
|
|
# Clone a project for next version
|
|
|
|
|
|
# Get actual branch
|
|
|
|
|
|
cmd_git_clone_migrate_source = (
|
|
|
|
|
|
f"cd {source_addons_path} && "
|
|
|
|
|
|
f"git branch --show-current && "
|
|
|
|
|
|
f"cd ~-"
|
|
|
|
|
|
)
|
|
|
|
|
|
status, cmd_executed, lst_output = self.todo_upgrade_execute(
|
|
|
|
|
|
cmd_git_clone_migrate_source,
|
|
|
|
|
|
get_output=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
branch_source = lst_output[0].strip() if len(lst_output) else ""
|
|
|
|
|
|
if not branch_source:
|
|
|
|
|
|
# Get branch from repo
|
|
|
|
|
|
branch_source = self.get_branch_name_from_local_manifest(
|
|
|
|
|
|
source_addons_path, f"{next_version}.0"
|
|
|
|
|
|
)
|
|
|
|
|
|
branch_target = branch_source.replace(
|
|
|
|
|
|
str(next_version - 1), str(next_version)
|
|
|
|
|
|
)
|
|
|
|
|
|
# Get remote branch for actual version
|
|
|
|
|
|
cmd_git_clone_migrate_source_same_target = (
|
|
|
|
|
|
f"cd {source_addons_path} "
|
|
|
|
|
|
f"&& git fetch --all "
|
|
|
|
|
|
f'&& git branch -vv | grep "{branch_source}" '
|
|
|
|
|
|
f"&& cd ~-"
|
|
|
|
|
|
)
|
|
|
|
|
|
cmd_git_clone_migrate_source_same_target_remote_only = (
|
|
|
|
|
|
f"cd {source_addons_path} && git remote && cd ~-"
|
|
|
|
|
|
)
|
|
|
|
|
|
status, cmd_executed, lst_output = self.todo_upgrade_execute(
|
|
|
|
|
|
cmd_git_clone_migrate_source_same_target,
|
|
|
|
|
|
get_output=True,
|
|
|
|
|
|
wait_at_error=False,
|
|
|
|
|
|
)
|
|
|
|
|
|
if status == 1:
|
|
|
|
|
|
status, cmd_executed, lst_output = self.todo_upgrade_execute(
|
|
|
|
|
|
cmd_git_clone_migrate_source_same_target_remote_only,
|
|
|
|
|
|
get_output=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
if lst_output:
|
|
|
|
|
|
remote = lst_output[0].strip()
|
|
|
|
|
|
# TODO write this modification into repo manifest
|
|
|
|
|
|
else:
|
|
|
|
|
|
remote = input(
|
|
|
|
|
|
"👹 BUG, you need to push last branch. Please write the remote/ :"
|
|
|
|
|
|
)
|
|
|
|
|
|
else:
|
|
|
|
|
|
local_branch, remote, remote_branch = (
|
|
|
|
|
|
self.get_local_branch_remote_actual_branch_git(
|
|
|
|
|
|
lst_output,
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
# Get remote branch for next version
|
|
|
|
|
|
remote_branch_target = f"{remote}/{branch_target}"
|
|
|
|
|
|
cmd_git_clone_migrate_source_same_target = (
|
|
|
|
|
|
f"cd {source_addons_path} "
|
|
|
|
|
|
f"&& git fetch --all "
|
|
|
|
|
|
f'&& git branch --remotes -vv | grep "{remote_branch_target} " '
|
|
|
|
|
|
f"&& cd ~-"
|
|
|
|
|
|
)
|
|
|
|
|
|
status, cmd_executed, lst_output = self.todo_upgrade_execute(
|
|
|
|
|
|
cmd_git_clone_migrate_source_same_target,
|
|
|
|
|
|
get_output=True,
|
|
|
|
|
|
wait_at_error=False,
|
|
|
|
|
|
)
|
|
|
|
|
|
has_existing_target_branch = any([a.strip() for a in lst_output])
|
|
|
|
|
|
|
|
|
|
|
|
# TODO check config if path is added
|
|
|
|
|
|
# Get remote branch address
|
|
|
|
|
|
cmd_remote_address = (
|
|
|
|
|
|
f"cd {source_addons_path} "
|
|
|
|
|
|
f"&& git remote get-url {remote} "
|
|
|
|
|
|
f"&& cd ~-"
|
|
|
|
|
|
)
|
|
|
|
|
|
status, cmd_executed, lst_output = self.todo_upgrade_execute(
|
|
|
|
|
|
cmd_remote_address,
|
|
|
|
|
|
get_output=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
remote_address = lst_output[0].strip()
|
|
|
|
|
|
|
|
|
|
|
|
# TODO some time, the clone has error, need to repeat
|
|
|
|
|
|
branch_to_clone = (
|
|
|
|
|
|
branch_target if has_existing_target_branch else branch_source
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
cmd_git_clone = (
|
|
|
|
|
|
f"cd {os.path.dirname(target_addons_path)} "
|
|
|
|
|
|
f"&& git clone {remote_address} {source_dir_name} -b {branch_to_clone} && cd ~-"
|
|
|
|
|
|
)
|
|
|
|
|
|
status, cmd_executed, lst_output = self.todo_upgrade_execute(
|
|
|
|
|
|
cmd_git_clone,
|
|
|
|
|
|
get_output=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
if not has_existing_target_branch:
|
|
|
|
|
|
cmd_git_clone = (
|
|
|
|
|
|
f"cd {target_addons_path} "
|
2026-06-29 03:22:58 -04:00
|
|
|
|
f"&& if git rev-parse --verify --quiet refs/heads/{branch_target}; then "
|
|
|
|
|
|
f"git checkout {branch_target}; else git checkout -b {branch_target}; fi "
|
|
|
|
|
|
f"&& cd ~-"
|
2025-10-31 01:10:54 -04:00
|
|
|
|
)
|
|
|
|
|
|
status, cmd_executed, lst_output = self.todo_upgrade_execute(
|
|
|
|
|
|
cmd_git_clone,
|
|
|
|
|
|
get_output=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def get_branch_name_from_local_manifest(self, addons_path, default_branch):
|
|
|
|
|
|
relative_addons_path = addons_path.replace(os.getcwd() + "/", "")
|
|
|
|
|
|
git_tool = GitTool()
|
|
|
|
|
|
dct_remote, dct_project, default_remote = (
|
|
|
|
|
|
git_tool.get_manifest_xml_info(filename=LOCAL_MANIFEST)
|
|
|
|
|
|
)
|
|
|
|
|
|
for dct_repo in dct_project.values():
|
|
|
|
|
|
path = dct_repo.get("@path")
|
|
|
|
|
|
if path == relative_addons_path:
|
|
|
|
|
|
revision = dct_repo.get("@revision")
|
|
|
|
|
|
return revision
|
|
|
|
|
|
return default_branch
|
|
|
|
|
|
|
|
|
|
|
|
def get_local_branch_remote_actual_branch_git(self, lst_output):
|
|
|
|
|
|
for line in lst_output:
|
|
|
|
|
|
# The current branch is marked with an asterisk (*) at the start of the line
|
|
|
|
|
|
if not line.strip().startswith("*"):
|
|
|
|
|
|
continue
|
|
|
|
|
|
# Split the line to isolate the remote and remote branch name
|
|
|
|
|
|
parts = line.split()
|
|
|
|
|
|
if len(parts) >= 4:
|
|
|
|
|
|
# The remote and remote branch are in the 4th part, e.g., '[origin/main]'
|
|
|
|
|
|
remote_info = parts[3].strip("[]")
|
|
|
|
|
|
# Split 'origin/main' into 'origin' and 'main'
|
|
|
|
|
|
# remote, remote_branch = remote_info.split("/", 1)
|
|
|
|
|
|
try:
|
|
|
|
|
|
remote, remote_branch = remote_info.split("/", 1)
|
|
|
|
|
|
except ValueError as e:
|
|
|
|
|
|
# # TODO this means no remote, take default one? or last one?
|
|
|
|
|
|
# # TODO supporter la migration 17 vers 18
|
|
|
|
|
|
# print("👹 BUG, you need to push ")
|
|
|
|
|
|
# TODO search remote and associate branch
|
|
|
|
|
|
value = input(
|
|
|
|
|
|
"👹 BUG, you need to push last branch. Please write the remote/branch_name :"
|
|
|
|
|
|
)
|
|
|
|
|
|
remote, remote_branch = value.split("/", 1)
|
|
|
|
|
|
return parts[1], remote, remote_branch
|
|
|
|
|
|
return None, None, None
|
|
|
|
|
|
|
|
|
|
|
|
def add_comment_progression(self, comment):
|
|
|
|
|
|
comment_to_add = f"# {comment}"
|
|
|
|
|
|
self.lst_command_executed.append(comment_to_add)
|
|
|
|
|
|
self.dct_progression["command_executed"] = self.lst_command_executed
|
|
|
|
|
|
self.write_config()
|