Merge branch 'develop'

- fix osx manifest
- update snap firefox ubuntu 25.10
- dynamic option to update config path addons from database or backup
This commit is contained in:
Mathieu Benoit 2026-02-14 04:55:11 -05:00
commit 4b0f9e15b7
18 changed files with 819 additions and 273 deletions

View file

@ -0,0 +1,66 @@
#!/usr/bin/env python3
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse
import logging
import os
import sys
new_path = os.path.normpath(
os.path.join(os.path.dirname(__file__), "..", "..")
)
sys.path.append(new_path)
from script.execute import execute
from script.git.git_tool import GitTool
_logger = logging.getLogger(__name__)
def get_config():
"""Parse command line arguments, extracting the config file name,
returning the union of config file and command line arguments
:return: dict of config file settings and command line arguments
"""
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description="""\
Will print list of installed module from database
""",
epilog="""\
""",
)
parser.add_argument(
"--database",
required=True,
help="The database name to extract",
)
args = parser.parse_args()
return args
def main():
config = get_config()
execute_cmd = execute.Execute()
if config.database:
cmd = f"cat ./script/odoo/util/show_installed_module.py | ./odoo_bin.sh shell -d {config.database}"
status, output = execute_cmd.exec_command_live(
cmd,
quiet=True,
source_erplibre=False,
single_source_erplibre=True,
return_status_and_output=True,
)
has_find = False
for line in output:
if has_find:
print(line.strip())
if line.strip() == "Installed modules:":
has_find = True
if __name__ == "__main__":
main()

View file

@ -0,0 +1,89 @@
#!/usr/bin/env python3
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse
import json
import logging
import os
import sys
import zipfile
new_path = os.path.normpath(
os.path.join(os.path.dirname(__file__), "..", "..")
)
sys.path.append(new_path)
from script.execute import execute
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"))
_logger = logging.getLogger(__name__)
def get_config():
"""Parse command line arguments, extracting the config file name,
returning the union of config file and command line arguments
:return: dict of config file settings and command line arguments
"""
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description="""\
Extract all repo path from installed module into backup.
Use --backup_path or --backup_name
""",
epilog="""\
""",
)
parser.add_argument("--backup_path", help="Backup file path")
parser.add_argument("--backup_name", help="Backup file name")
parser.add_argument(
"--debug",
action="store_true",
help="Will show all debug and execution information",
)
args = parser.parse_args()
die(
not (bool(args.backup_path) or bool(args.backup_name)),
"Take --backup_path or --backup_name",
)
return args
def main():
config = get_config()
if config.backup_path:
file_path = config.backup_path
elif not config.backup_name.endswith(".zip"):
file_path = os.path.join("image_db", f"{config.backup_name}.zip")
else:
file_path = os.path.join("image_db", config.backup_name)
with zipfile.ZipFile(file_path, "r") as zip_ref:
manifest_file = zip_ref.open("manifest.json")
json_manifest_file = json.load(manifest_file)
lst_module = set(json_manifest_file.get("modules").keys())
str_module = ";".join(lst_module)
cmd = f'./script/database/get_repo_from_module.py --module "{str_module}"'
execute_cmd = execute.Execute()
status, output = execute_cmd.exec_command_live(
cmd,
source_erplibre=False,
single_source_erplibre=True,
return_status_and_output=True,
)
def die(cond, message, code=1):
if cond:
print(message, file=sys.stderr)
sys.exit(code)
if __name__ == "__main__":
main()

View file

@ -0,0 +1,80 @@
#!/usr/bin/env python3
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import argparse
import json
import logging
import os
import sys
import zipfile
new_path = os.path.normpath(
os.path.join(os.path.dirname(__file__), "..", "..")
)
sys.path.append(new_path)
from script.execute import execute
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"))
_logger = logging.getLogger(__name__)
def get_config():
"""Parse command line arguments, extracting the config file name,
returning the union of config file and command line arguments
:return: dict of config file settings and command line arguments
"""
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description="""\
Extract all repo path from installed module into backup.
Use --backup_path or --backup_name
""",
epilog="""\
""",
)
parser.add_argument("--module", help="Module list separate by ;")
parser.add_argument("--debug", action="store_true")
args = parser.parse_args()
return args
def main():
config = get_config()
lst_module = set(config.module.split(";"))
cmd = "parallel ::: " + " ".join(
[
f"'./script/addons/check_addons_exist.py --output_path -m \"{a}\"'"
for a in lst_module
]
)
execute_cmd = execute.Execute()
status, output = execute_cmd.exec_command_live(
cmd,
quiet=not config.debug,
source_erplibre=False,
single_source_erplibre=True,
return_status_and_output=True,
)
set_path_repo = set()
for line_module_path in output:
line_repo = os.path.dirname(line_module_path)
set_path_repo.add(line_repo)
for path_repo in set_path_repo:
print(path_repo)
def die(cond, message, code=1):
if cond:
print(message, file=sys.stderr)
sys.exit(code)
if __name__ == "__main__":
main()

View file

@ -359,6 +359,7 @@ def run_cmd(cmd, quiet=False, sys_exit=True):
if not quiet:
_logger.info(f"Run cmd: {cmd}")
debut = time.time()
# Maybe can use exec_command_live
process = subprocess.Popen(
cmd,
shell=True,

View file

189
script/execute/execute.py Normal file
View file

@ -0,0 +1,189 @@
#!/usr/bin/env python3
# © 2021-2025 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import datetime
import logging
import os
import shutil
import subprocess
import sys
import time
import humanize
cst_venv_erplibre = ".venv.erplibre"
new_path = os.path.normpath(
os.path.join(os.path.dirname(__file__), "..", "..")
)
sys.path.append(new_path)
logging.basicConfig(
format=(
"%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d]"
" %(message)s"
),
datefmt="%Y-%m-%d:%H:%M:%S",
level=logging.INFO,
)
_logger = logging.getLogger(__name__)
class Execute:
def __init__(self):
self.cmd_source_erplibre = ""
self.cmd_source_default = ""
exec_path_gnome_terminal = shutil.which("gnome-terminal")
if exec_path_gnome_terminal:
self.cmd_source_erplibre = (
f"gnome-terminal -- bash -c 'source"
f" ./{cst_venv_erplibre}/bin/activate;%s'"
)
self.cmd_source_default = "gnome-terminal -- bash -c '" f"%s'"
else:
exec_path_tell = shutil.which("osascript")
if exec_path_tell:
self.cmd_source_erplibre = (
"osascript -e 'tell application \"Terminal\"'"
)
self.cmd_source_erplibre += " -e 'tell application \"System Events\" to keystroke \"t\" using {command down}' -e 'delay 0.1' -e 'do script \""
self.cmd_source_erplibre += f"cd {os.getcwd()}; source ./{cst_venv_erplibre}/bin/activate; %s\" in front window'"
self.cmd_source_erplibre += " -e 'end tell'"
else:
self.cmd_source_erplibre = (
f"source ./{cst_venv_erplibre}/bin/activate;%s"
)
def exec_command_live(
self,
commande,
source_erplibre=True,
quiet=False,
single_source_erplibre=False,
new_window=False,
single_source_odoo=False,
source_odoo="",
new_env=None,
return_status_and_command=False,
return_status_and_output=False,
return_status_and_output_and_command=False,
):
"""
Exécute une commande et affiche la sortie en direct.
Args:
commande (str): La commande à exécuter (sous forme de chaîne de caractères).
"""
my_env = os.environ.copy()
if new_env:
my_env.update(new_env)
process_start_time = time.time()
return_status = None
if source_erplibre:
# commande = f"source ./{cst_venv_erplibre}/bin/activate && " + commande
# cmd = (
# f"gnome-terminal --tab -- bash -c 'source"
# f" ./{cst_venv_erplibre}/bin/activate;{commande}'"
# )
commande = self.cmd_source_erplibre % commande
# os.system(f"./script/terminal/open_terminal.sh {commande}")
elif single_source_erplibre:
commande = (
f"source ./{cst_venv_erplibre}/bin/activate && %s" % commande
)
elif single_source_odoo:
if not source_odoo and os.path.exists("./.erplibre-version"):
with open("./.erplibre-version") as f:
source_odoo = f.read()
if not source_odoo:
_logger.error(
f"You cannot execute Odoo command if no version is installed. Command : {commande}"
)
return -1
commande = (
f"source ./.venv.{source_odoo}/bin/activate && {commande}"
)
if new_window and self.cmd_source_default:
commande = self.cmd_source_default % commande
if not quiet:
print("🏠 ⬇ Execute command :")
print(commande)
lst_output = []
try:
process = subprocess.Popen(
commande,
shell=True,
executable="/bin/bash",
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1, # Désactive la mise en tampon pour la sortie en direct
universal_newlines=True, # Pour traiter les sauts de lignes correctement
env=my_env,
)
while True:
ligne = process.stdout.readline()
if not ligne:
break
if not quiet:
print(ligne, end="")
if (
return_status_and_output
or return_status_and_output_and_command
):
# Remove last \n char
lst_output.append(
ligne.removesuffix("\r\n")
.removesuffix("\n")
.removesuffix("\r")
)
process.wait() # Attendre la fin du process
return_status = process.returncode
if process.returncode != 0 and not quiet:
print(
"La commande a retourné un code d'erreur :"
f" {process.returncode}"
)
except FileNotFoundError:
if not quiet:
if "password" in commande:
print(
f"Erreur : La commande '{commande.split(' ')[0]}'[...] n'a"
" pas été trouvée."
)
else:
print(
f"Erreur : La commande '{commande}' n'a pas été trouvée."
)
except Exception as e:
if not quiet:
print(f"Une erreur s'est produite : {e}")
process_end_time = time.time()
duration_sec = process_end_time - process_start_time
if humanize:
duration_delta = datetime.timedelta(seconds=duration_sec)
humain_time = humanize.precisedelta(duration_delta)
if not quiet:
print(f"🏠 ⬆ Executed ({humain_time}) :")
else:
if not quiet:
print(f"🏠 ⬆ Executed ({duration_sec:.2f} sec.) :")
if not quiet:
print(commande)
print()
if return_status_and_output_and_command:
return return_status, commande, lst_output
if return_status_and_command:
return return_status, commande
if return_status_and_output:
return return_status, lst_output
return return_status

View file

@ -7,14 +7,12 @@ import logging
import os
import sys
import git
from git import Repo
new_path = os.path.normpath(
os.path.join(os.path.dirname(__file__), "..", "..")
)
sys.path.append(new_path)
from script.execute import execute
from script.git.git_tool import GitTool
_logger = logging.getLogger(__name__)
@ -26,9 +24,6 @@ def get_config():
:return: dict of config file settings and command line arguments
"""
config = GitTool.get_project_config()
# TODO update description
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description="""\
@ -52,6 +47,22 @@ def get_config():
action="store_true",
help="Will remove odoo path, need this feature for OpenUpgrade when Odoo <= 13",
)
parser.add_argument(
"--from_backup_path",
help="Will read backup path and whitelist the repo",
)
parser.add_argument(
"--from_backup_name",
help="Will read backup name and whitelist the repo",
)
parser.add_argument(
"--add_repo",
help="Add repo, separate by ; for list",
)
parser.add_argument(
"--database",
help="Add repo from module found into database.",
)
args = parser.parse_args()
return args
@ -59,13 +70,63 @@ def get_config():
def main():
config = get_config()
git_tool = GitTool()
execute_cmd = execute.Execute()
index_to_remove = len(os.getcwd()) + 1
filter_group = config.group if config.group else None
lst_whitelist = []
if config.from_backup_path or config.from_backup_name:
# script/database/get_repo_from_backup.py
# --backup_name bpir_prod_5_dec_2025_2026-02-04_14h27m54s.zip
if config.from_backup_path:
cmd = f"./script/database/get_repo_from_backup.py --backup_path {config.from_backup_path}"
else:
cmd = f"./script/database/get_repo_from_backup.py --backup_name {config.from_backup_name}"
status, output = execute_cmd.exec_command_live(
cmd,
quiet=True,
source_erplibre=False,
single_source_erplibre=True,
return_status_and_output=True,
)
for line in output:
repo_name = line[index_to_remove:].strip()
lst_whitelist.append(repo_name)
if config.database:
cmd = f"./script/database/get_module_list_from_database.py --database {config.database}"
status, output = execute_cmd.exec_command_live(
cmd,
quiet=True,
source_erplibre=False,
single_source_erplibre=True,
return_status_and_output=True,
)
str_module = ";".join(output)
cmd = f'./script/database/get_repo_from_module.py --module "{str_module}"'
status, output = execute_cmd.exec_command_live(
cmd,
quiet=True,
source_erplibre=False,
single_source_erplibre=True,
return_status_and_output=True,
)
for line in output:
repo_name = line[index_to_remove:].strip()
lst_whitelist.append(repo_name)
if config.add_repo:
lst_add_repo = [a.strip() for a in config.add_repo.split(";")]
else:
lst_add_repo = []
git_tool.generate_generate_config(
filter_group=filter_group,
extra_path=config.extra_addons_path,
ignore_odoo_path=config.ignore_odoo_path,
lst_add_repo=lst_add_repo,
lst_whitelist=lst_whitelist,
)

View file

@ -74,7 +74,7 @@ class GitTool:
def get_transformed_repo_info_from_url(
self,
url: str,
repo_path: str = "./",
repo_path: str = ".",
get_obj: bool = True,
is_submodule: bool = True,
organization_force: str = None,
@ -103,15 +103,16 @@ class GitTool:
repo_name = repo_name[:-4]
if is_submodule:
if not sub_path or sub_path == ".":
path = f"{repo_name}"
path = repo_name
else:
path = f"{sub_path}/{organization}_{repo_name}"
path = os.path.join(sub_path, f"{organization}_{repo_name}")
else:
path = f"{repo_path}"
if repo_path[-1] == "/":
relative_path = f"{repo_path}{path}"
else:
relative_path = f"{repo_path}/{path}"
path = repo_path
relative_path = os.path.join(repo_path, path)
# if repo_path[-1] == "/":
# relative_path = f"{repo_path}{path}"
# else:
# relative_path = f"{repo_path}/{path}"
relative_path = os.path.normpath(relative_path)
original_organization = organization
@ -150,7 +151,7 @@ class GitTool:
def get_repo_info(
self,
repo_path: str = "./",
repo_path: str = ".",
add_root: bool = False,
is_manifest: bool = True,
filter_group=None,
@ -166,7 +167,7 @@ class GitTool:
)
def get_repo_info_submodule(
self, repo_path: str = "./", add_root: bool = False
self, repo_path: str = ".", add_root: bool = False
) -> list:
"""
Get information about submodule from repo_path
@ -182,7 +183,7 @@ class GitTool:
"name": name of the submodule
}]
"""
filename = f"{repo_path}/.gitmodules"
filename = os.path.join(repo_path, ".gitmodules")
lst_repo = []
with open(filename) as file:
txt = file.readlines()
@ -200,7 +201,7 @@ class GitTool:
"url_https": url_https,
"url_git": url_git,
"path": path,
"relative_path": f"{repo_path}/{path}",
"relative_path": os.path.join(repo_path, path),
"name": name,
}
lst_repo.append(data)
@ -225,7 +226,7 @@ class GitTool:
"url_https": url_https,
"url_git": url_git,
"path": path,
"relative_path": f"{repo_path}/{path}",
"relative_path": os.path.join(repo_path, path),
"name": name,
}
lst_repo.append(data)
@ -248,7 +249,7 @@ class GitTool:
return lst_repo
def get_repo_info_manifest_xml(
self, repo_path: str = "./", add_root: bool = False, filter_group=None
self, repo_path: str = ".", add_root: bool = False, filter_group=None
) -> list:
"""
Get information about manifest of Repo from repo_path
@ -318,7 +319,7 @@ class GitTool:
"url_https": url_https,
"url_git": url_git,
"path": path,
"relative_path": f"{repo_path}/{path}",
"relative_path": os.path.join(repo_path, path),
"name": name,
"group": groups,
}
@ -351,7 +352,7 @@ class GitTool:
return lst_repo
def get_manifest_xml_info(
self, repo_path: str = "./", filename=None, add_root: bool = False
self, repo_path: str = ".", filename=None, add_root: bool = False
) -> list:
"""
Get contain of manifest
@ -388,7 +389,7 @@ class GitTool:
return dct_remote, dct_project, default_remote
@staticmethod
def get_project_config(repo_path="./"):
def get_project_config(repo_path="."):
"""
Get information about configuration in env_var.sh
:param repo_path: path of repo to get information env_var.sh
@ -397,7 +398,7 @@ class GitTool:
CST_EL_GITHUB_TOKEN: TOKEN,
}
"""
filename = f"{repo_path}env_var.sh"
filename = os.path.join(repo_path, "env_var.sh")
with open(filename) as file:
txt = file.readlines()
txt = [a[:-1] for a in txt if "=" in a]
@ -421,17 +422,29 @@ class GitTool:
def generate_generate_config(
self,
repo_path="./",
repo_path=".",
filter_group=None,
extra_path=None,
ignore_odoo_path=None,
lst_add_repo=None,
lst_whitelist=None,
):
filename_locally = f"{repo_path}script/generate_config.sh"
filename_locally = os.path.join(repo_path, "script/generate_config.sh")
if not filter_group:
filter_group = self.odoo_version_long
lst_repo = self.get_repo_info(
lst_repo_origin = self.get_repo_info(
repo_path=repo_path, filter_group=filter_group
)
if lst_whitelist:
lst_repo = []
for repo in lst_repo_origin:
if (
repo.get("path") in lst_whitelist
or repo.get("path") in lst_add_repo
):
lst_repo.append(repo)
else:
lst_repo = lst_repo_origin
lst_result = []
if not lst_repo:
print(
@ -444,7 +457,9 @@ class GitTool:
continue
# groups = repo.get("group")
# Use variable instead of hardcoded path
if update_repo.startswith(f"{filter_group}/addons"):
if update_repo.startswith(
os.path.join(self.odoo_version_long, "addons")
):
lst_path = update_repo.split("/", 1)
update_repo = f"${{EL_HOME_ODOO_PROJECT}}/" + lst_path[1]
# str_repo = (
@ -715,7 +730,7 @@ class GitTool:
print(str_xml_text + "\n")
def generate_git_modules(
self, lst_repo: List[Struct], repo_path: str = "./"
self, lst_repo: List[Struct], repo_path: str = "."
):
lst_modules = []
for repo in lst_repo:
@ -727,10 +742,10 @@ class GitTool:
)
# create file
with open(f"{repo_path}.gitmodules", mode="w") as file:
with open(os.path.join(repo_path, ".gitmodules"), mode="w") as file:
file.writelines(lst_modules)
def get_source_repo_addons(self, repo_path="./", add_repo_root=False):
def get_source_repo_addons(self, repo_path=".", add_repo_root=False):
"""
Read file CST_FILE_SOURCE_REPO_ADDONS and return structure of data
:param repo_path: path to find file CST_FILE_SOURCE_REPO_ADDONS
@ -745,7 +760,7 @@ class GitTool:
"name": name of the submodule
}]
"""
file_name = f"{repo_path}{CST_FILE_SOURCE_REPO_ADDONS}"
file_name = os.path.join(repo_path, CST_FILE_SOURCE_REPO_ADDONS)
lst_result = []
if add_repo_root:
# TODO what to do if origin not exist?
@ -800,7 +815,7 @@ class GitTool:
lst_result.append(repo_info)
return lst_result
def get_manifest_file(self, repo_path: str = "./"):
def get_manifest_file(self, repo_path: str = "."):
"""
Find .repo and return default manifest file.
:param repo_path: path to search .repo
@ -811,7 +826,7 @@ class GitTool:
)
if os.path.exists(file):
return file
file = f"{repo_path}/.repo/manifest.xml"
file = os.path.join(repo_path, ".repo/manifest.xml")
if not os.path.exists(file):
return ""
with open(file) as xml:
@ -824,8 +839,8 @@ class GitTool:
def get_matching_repo(
self,
actual_repo="./",
repo_compare_to="./",
actual_repo=".",
repo_compare_to=".",
force_normalize_compare=False,
sync_with_submodule=False,
):

View file

@ -12,7 +12,7 @@ EL_USER=${USER}
#--------------------------------------------------
# Install PostgreSQL Server
#--------------------------------------------------
echo "\n---- Install PostgreSQL Server ----"
echo "\n---- Install PostgreSQL Server ----"
if which psql >/dev/null 2>&1; then
echo "postgresql is already installed, skipping"
else
@ -21,39 +21,39 @@ else
brew services start postgresql@15
fi
echo "\n---- Creating the ERPLibre PostgreSQL User ----"
sudo su - postgres -c "createuser -s ${EL_USER}" 2> /dev/null || true
sudo su - postgres -c "CREATE EXTENSION postgis;\nCREATE EXTENSION postgis_topology;" 2> /dev/null || true
echo "\n---- Creating the ERPLibre PostgreSQL User ----"
sudo su - postgres -c "createuser -s ${EL_USER}" 2>/dev/null || true
sudo su - postgres -c "CREATE EXTENSION postgis;\nCREATE EXTENSION postgis_topology;" 2>/dev/null || true
#--------------------------------------------------
# Install Dependencies
#--------------------------------------------------
echo "\n--- Installing Python 3 + pip3 --"
#TODO is python@3.7 line here still usefull?? Should we get rid of it?
brew install git python@3.7 wget parallel mariadb
echo "\n--- Installing Python 3 + pip3 --"
brew install git wget parallel mariadb
brew link git
brew link wget
echo "\n--- Installing extra --"
echo "\n--- Installing extra --"
brew install shfmt
brew install parallel
brew install swig
brew install portaudio
brew install xmlsec1
echo "\n---- Installing nodeJS NPM and rtlcss for LTR support ----"
echo "\n---- Installing nodeJS NPM and rtlcss for LTR support ----"
brew install nodejs npm openssl
sudo npm install -g rtlcss
sudo npm install -g less
npm install
echo 'export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"' >> ~/.zshrc
echo 'export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"' >>~/.zshrc
#--------------------------------------------------
# Install Wkhtmltopdf if needed
#--------------------------------------------------
echo "\n---- Installing Wkhtmltopdf if needed ----"
echo "\n---- Installing Wkhtmltopdf if needed ----"
if [ ! -f "wkhtmltox-0.12.6-2.macos-cocoa.pkg" ]; then
sudo wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-2/wkhtmltox-0.12.6-2.macos-cocoa.pkg
sudo sudo installer -pkg wkhtmltox-0.12.6-2.macos-cocoa.pkg -target /
else echo "Wkhtmltopdf already installed"
else
echo "Wkhtmltopdf already installed"
fi

View file

@ -14,10 +14,16 @@ else
MANIFEST_TARGET="$EL_MANIFEST_DEV"
fi
if command -v nproc >/dev/null 2>&1; then
JOBS="$(nproc --all)"
else
JOBS="$(sysctl -n hw.ncpu)"
fi
# Generate local manifest
.venv.erplibre/bin/python ./script/git/git_merge_repo_manifest.py --output .repo/local_manifests/erplibre_manifest.xml --with_OCA
.venv.erplibre/bin/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --verify HEAD) -m ${MANIFEST_TARGET} "$@"
.venv.erplibre/bin/repo sync -c -j $(nproc --all) -v -m ${MANIFEST_TARGET}
.venv.erplibre/bin/repo sync -c -j "$JOBS" -v -m ${MANIFEST_TARGET}
kill ${DAEMON_PID}

View file

@ -15,7 +15,13 @@ else
MANIFEST_TARGET="$EL_MANIFEST_DEV"
fi
if command -v nproc >/dev/null 2>&1; then
JOBS="$(nproc --all)"
else
JOBS="$(sysctl -n hw.ncpu)"
fi
.venv.erplibre/bin/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --verify HEAD) -m ${MANIFEST_TARGET} -g base,code_generator
.venv.erplibre/bin/repo sync -c -j $(nproc --all) -v -m ${MANIFEST_TARGET}
.venv.erplibre/bin/repo sync -c -j "$JOBS" -v -m ${MANIFEST_TARGET}
kill ${DAEMON_PID}

View file

@ -14,10 +14,16 @@ else
MANIFEST_TARGET="$EL_MANIFEST_DEV"
fi
if command -v nproc >/dev/null 2>&1; then
JOBS="$(nproc --all)"
else
JOBS="$(sysctl -n hw.ncpu)"
fi
# Generate local manifest
.venv.erplibre/bin/python ./script/git/git_merge_repo_manifest.py --output .repo/local_manifests/erplibre_manifest.xml --with_mobile
.venv.erplibre/bin/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --verify HEAD) -m ${MANIFEST_TARGET} "$@"
.venv.erplibre/bin/repo sync -c -j $(nproc --all) -v -m ${MANIFEST_TARGET}
.venv.erplibre/bin/repo sync -c -j "$JOBS" -v -m ${MANIFEST_TARGET}
kill ${DAEMON_PID}

View file

@ -15,7 +15,13 @@ else
MANIFEST_TARGET="$EL_MANIFEST_DEV"
fi
if command -v nproc >/dev/null 2>&1; then
JOBS="$(nproc --all)"
else
JOBS="$(sysctl -n hw.ncpu)"
fi
.venv.erplibre/bin/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --verify HEAD) -m ${MANIFEST_TARGET}
.venv.erplibre/bin/repo sync -c -j $(nproc --all) -v -m ${MANIFEST_TARGET}
.venv.erplibre/bin/repo sync -c -j "$JOBS" -v -m ${MANIFEST_TARGET}
kill ${DAEMON_PID}

View file

@ -5,6 +5,12 @@
#EL_MANIFEST_PROD="./default.xml"
#EL_MANIFEST_DEV="./manifest/default.dev.xml"
if command -v nproc >/dev/null 2>&1; then
JOBS="$(nproc --all)"
else
JOBS="$(sysctl -n hw.ncpu)"
fi
# Update git-repo
.venv.erplibre/bin/repo init -u https://github.com/ERPLibre/ERPLibre -b $(git rev-parse --verify HEAD)
.venv.erplibre/bin/repo sync -v -j $(nproc --all)
.venv.erplibre/bin/repo sync -v -j "$JOBS"

View file

@ -3,7 +3,7 @@
Run this script when doing database migration. Example :
```bash
source ./.venv.odoo15.0_python3.8.20/bin/activate && cat ./script/migration/fix_migration_odoo140_to_odoo150.py | ./odoo15.0/odoo/odoo-bin shell -d DATABASE
source ./.venv.odoo15.0_python3.8.20/bin/activate && cat ./script/odoo/migration/fix_migration_odoo140_to_odoo150.py | ./odoo15.0/odoo/odoo-bin shell -d DATABASE
```
Check [uninstall_module_list_odoo140_to_odoo150.txt](uninstall_module_list_odoo140_to_odoo150.txt)

View file

@ -13,6 +13,7 @@ import sys
import tempfile
import time
import tkinter as tk
from pathlib import Path
from tkinter import filedialog
from pykeepass import PyKeePass
@ -226,10 +227,18 @@ class SeleniumLib(object):
self.config.firefox_binary_path
)
elif not self.config.use_network:
status_location = subprocess.check_output(
["which", "firefox"], text=True
).strip()
firefox_options.binary_location = status_location
# test snap firefox for Ubuntu first
snap_firefox_path = (
"/snap/firefox/current/usr/lib/firefox/firefox"
)
firefox_path_exist = Path(snap_firefox_path).exists()
if firefox_path_exist:
firefox_options.binary_location = snap_firefox_path
else:
status_location = subprocess.check_output(
["which", "firefox"], text=True
).strip()
firefox_options.binary_location = status_location
firefox_profile = webdriver.FirefoxProfile()
firefox_profile.set_preference(

View file

@ -54,6 +54,8 @@ try:
# import rich
import todo_upgrade
from pykeepass import PyKeePass
from script.execute import execute
except ModuleNotFoundError as e:
humanize = None
ENABLE_CRASH = True
@ -81,34 +83,9 @@ class TODO:
def __init__(self):
self.dir_path = None
self.kdbx = None
self.init()
self.file_path = None
self.config_file = config_file.ConfigFile()
def init(self):
# Get command
self.cmd_source_erplibre = ""
self.cmd_source_default = ""
exec_path_gnome_terminal = shutil.which("gnome-terminal")
if exec_path_gnome_terminal:
self.cmd_source_erplibre = (
f"gnome-terminal -- bash -c 'source"
f" ./{cst_venv_erplibre}/bin/activate;%s'"
)
self.cmd_source_default = "gnome-terminal -- bash -c '" f"%s'"
else:
exec_path_tell = shutil.which("osascript")
if exec_path_tell:
self.cmd_source_erplibre = (
"osascript -e 'tell application \"Terminal\"'"
)
self.cmd_source_erplibre += " -e 'tell application \"System Events\" to keystroke \"t\" using {command down}' -e 'delay 0.1' -e 'do script \""
self.cmd_source_erplibre += f"cd {os.getcwd()}; source ./{cst_venv_erplibre}/bin/activate; %s\" in front window'"
self.cmd_source_erplibre += " -e 'end tell'"
else:
self.cmd_source_erplibre = (
f"source ./{cst_venv_erplibre}/bin/activate;%s"
)
self.execute = execute.Execute()
def run(self):
with open(self.config_file.get_logo_ascii_file_path()) as my_file:
@ -150,7 +127,7 @@ class TODO:
# f" ./{cst_venv_erplibre}/bin/activate;make todo'"
# )
cmd = "make todo"
self.executer_commande_live(cmd, source_erplibre=True)
self.execute.exec_command_live(cmd, source_erplibre=True)
# elif status == "3" or status == "install":
# print("install")
else:
@ -229,6 +206,7 @@ class TODO:
[5] Doc - Recherche de documentation
[6] Database - Outils sur les bases de données
[7] Process - Outils sur les exécutions
[8] Config - Traitement du fichier de configuration
[0] Retour
"""
while True:
@ -264,6 +242,10 @@ class TODO:
status = self.prompt_execute_process()
if status is not False:
return
elif status == "8":
status = self.prompt_execute_config()
if status is not False:
return
else:
print("Commande non trouvée 🤖!")
@ -280,7 +262,7 @@ class TODO:
)
if first_installation_input == "y":
cmd = "./script/version/update_env_version.py --install"
self.executer_commande_live(cmd, source_erplibre=True)
self.execute.exec_command_live(cmd, source_erplibre=True)
print("Wait after OS installation before continue.")
# First detect pycharm, need to be open before installation and close to increase speed
@ -312,7 +294,7 @@ class TODO:
pycharm_bin = "pycharm" if has_pycharm else "pycharm-community"
cmd = f"cd {os.getcwd()} && {pycharm_bin} ./"
self.executer_commande_live(
self.execute.exec_command_live(
cmd,
source_erplibre=False,
single_source_erplibre=False,
@ -432,7 +414,7 @@ class TODO:
makefile_cmd = dct_instance.get("makefile_cmd")
if makefile_cmd and not ignore_makefile:
status = self.executer_commande_live(
status = self.execute.exec_command_live(
f"make {makefile_cmd}",
source_erplibre=False,
single_source_erplibre=True,
@ -459,10 +441,10 @@ class TODO:
if callback:
callback(dct_instance)
def fill_help_info(self, lst_instance):
def fill_help_info(self, lst_choice):
help_info = "Commande :\n"
help_end = "[0] Retour\n"
for i, dct_instance in enumerate(lst_instance):
for i, dct_instance in enumerate(lst_choice):
help_info += (
f"[{i + 1}] " + dct_instance["prompt_description"] + "\n"
)
@ -473,16 +455,16 @@ class TODO:
# TODO proposer le déploiement à distance
# TODO proposer l'exécution de docker
# TODO proposer la création de docker
lst_instance = self.config_file.get_config("instance")
init_len = len(lst_instance)
lst_choice = self.config_file.get_config("instance")
init_len = len(lst_choice)
if os.path.exists(MOBILE_HOME_PATH):
dct_upgrade_odoo_database = {
"prompt_description": "Mobile - Compile and run software",
"callback": self.callback_make_mobile_home,
}
lst_instance.append(dct_upgrade_odoo_database)
help_info = self.fill_help_info(lst_instance)
lst_choice.append(dct_upgrade_odoo_database)
help_info = self.fill_help_info(lst_choice)
while True:
status = click.prompt(help_info)
@ -498,15 +480,15 @@ class TODO:
status = click.confirm(
"Voulez-vous une nouvelle instance?"
)
dct_instance = lst_instance[int_cmd - 1]
dct_instance = lst_choice[int_cmd - 1]
self.execute_from_configuration(
dct_instance,
exec_run_db=True,
ignore_makefile=not bool(status),
)
elif int_cmd <= len(lst_instance):
elif int_cmd <= len(lst_choice):
# Execute dynamic instance
dct_instance = lst_instance[int_cmd - 1]
dct_instance = lst_choice[int_cmd - 1]
self.execute_from_configuration(
dct_instance,
)
@ -516,8 +498,8 @@ class TODO:
print("Commande non trouvée 🤖!")
def prompt_execute_fonction(self):
lst_instance = self.config_file.get_config("function")
help_info = self.fill_help_info(lst_instance)
lst_choice = self.config_file.get_config("function")
help_info = self.fill_help_info(lst_choice)
while True:
status = click.prompt(help_info)
@ -528,9 +510,9 @@ class TODO:
cmd_no_found = True
try:
int_cmd = int(status)
if 0 < int_cmd <= len(lst_instance):
if 0 < int_cmd <= len(lst_choice):
cmd_no_found = False
dct_instance = lst_instance[int_cmd - 1]
dct_instance = lst_choice[int_cmd - 1]
self.execute_from_configuration(dct_instance)
except ValueError:
pass
@ -538,7 +520,7 @@ class TODO:
print("Commande non trouvée 🤖!")
def prompt_execute_update(self):
# self.executer_commande_live(f"make {makefile_cmd}")
# self.execute.exec_command_live(f"make {makefile_cmd}")
print("🤖 Mise à jour du développement")
# TODO détecter les modules en modification pour faire la mise à jour en cours
# TODO demander sur quel BD faire la mise à jour
@ -548,34 +530,34 @@ class TODO:
# TODO faire la mise à jour de ERPLibre
# TODO faire l'upgrade d'un odoo vers un autre
lst_instance = self.config_file.get_config("update_from_makefile")
lst_choice = self.config_file.get_config("update_from_makefile")
dct_upgrade_odoo_database = {
"prompt_description": "Upgrade Odoo - Migration Database",
}
lst_instance.append(dct_upgrade_odoo_database)
lst_choice.append(dct_upgrade_odoo_database)
dct_upgrade_poetry = {
"prompt_description": "Upgrade Poetry - Dependency of Odoo",
}
lst_instance.append(dct_upgrade_poetry)
help_info = self.fill_help_info(lst_instance)
lst_choice.append(dct_upgrade_poetry)
help_info = self.fill_help_info(lst_choice)
while True:
status = click.prompt(help_info)
print()
if status == "0":
return False
elif status == str(len(lst_instance) - 1):
elif status == str(len(lst_choice) - 1):
upgrade = todo_upgrade.TodoUpgrade(self)
upgrade.execute_odoo_upgrade()
elif status == str(len(lst_instance)):
elif status == str(len(lst_choice)):
self.upgrade_poetry()
else:
cmd_no_found = True
try:
int_cmd = int(status) - 1
if 0 < int_cmd <= len(lst_instance):
if 0 < int_cmd <= len(lst_choice):
cmd_no_found = False
dct_instance = lst_instance[int_cmd - 1]
dct_instance = lst_choice[int_cmd - 1]
self.execute_from_configuration(dct_instance)
except ValueError:
pass
@ -596,27 +578,36 @@ class TODO:
# [0] Retour
# """
lst_instance = self.config_file.get_config("code_from_makefile")
lst_choice = self.config_file.get_config("code_from_makefile")
dct_upgrade_odoo_database = {
"prompt_description": "Open SHELL",
}
lst_choice.append(dct_upgrade_odoo_database)
dct_upgrade_odoo_database = {
"prompt_description": "Upgrade Module",
}
lst_instance.append(dct_upgrade_odoo_database)
help_info = self.fill_help_info(lst_instance)
lst_choice.append(dct_upgrade_odoo_database)
help_info = self.fill_help_info(lst_choice)
while True:
status = click.prompt(help_info)
print()
if status == "0":
return False
elif status == str(len(lst_instance)):
elif status == str(len(lst_choice)):
self.upgrade_module()
elif status == str(len(lst_choice) - 1):
self.open_shell_on_database()
else:
cmd_no_found = True
try:
int_cmd = int(status)
if 0 < int_cmd <= len(lst_instance):
if 0 < int_cmd <= len(lst_choice):
cmd_no_found = False
dct_instance = lst_instance[int_cmd - 1]
dct_instance = lst_choice[int_cmd - 1]
self.execute_from_configuration(dct_instance)
except ValueError:
pass
@ -625,13 +616,13 @@ class TODO:
def prompt_execute_doc(self):
print("🤖 Vous cherchez de la documentation?")
lst_instance = [
lst_choice = [
{"prompt_description": "Migration module coverage"},
{"prompt_description": "What change between version"},
{"prompt_description": "OCA guidelines"},
{"prompt_description": "OCA migration Odoo 19 milestone"},
]
help_info = self.fill_help_info(lst_instance)
help_info = self.fill_help_info(lst_choice)
while True:
status = click.prompt(help_info)
@ -674,13 +665,13 @@ class TODO:
def prompt_execute_database(self):
print("🤖 Faites des modifications sur les bases de données!")
lst_instance = [
lst_choice = [
{
"prompt_description": "Download database to create backup (.zip)"
},
{"prompt_description": "Restore from backup (.zip)"},
]
help_info = self.fill_help_info(lst_instance)
help_info = self.fill_help_info(lst_choice)
while True:
status = click.prompt(help_info)
@ -696,10 +687,10 @@ class TODO:
def prompt_execute_process(self):
print("🤖 Manipuler les processus d'exécution!")
lst_instance = [
lst_choice = [
{"prompt_description": "Kill process from actual port"},
]
help_info = self.fill_help_info(lst_instance)
help_info = self.fill_help_info(lst_choice)
while True:
status = click.prompt(help_info)
@ -711,6 +702,122 @@ class TODO:
else:
print("Commande non trouvée 🤖!")
def prompt_execute_config(self):
print("🤖 Manipuler la configuration ERPLibre et Odoo!")
lst_choice = [
{"prompt_description": "Generate all configuration"},
{"prompt_description": "Generate from pre-configuration"},
{"prompt_description": "Generate from backup file"},
{"prompt_description": "Generate from database"},
]
help_info = self.fill_help_info(lst_choice)
while True:
status = click.prompt(help_info)
print()
if status == "0":
return False
elif status == "1":
self.generate_config()
elif status == "2":
self.generate_config_from_preconfiguration()
elif status == "3":
self.generate_config_from_backup()
elif status == "4":
self.generate_config_from_database()
else:
print("Commande non trouvée 🤖!")
def generate_config(self, add_arg=None):
# Repeating to get all item before get group
cmd = (
f"./script/git/git_repo_update_group.py;"
f"./script/generate_config.sh"
)
if add_arg:
cmd += (
f";./script/git/git_repo_update_group.py {add_arg};"
f"./script/generate_config.sh"
)
self.execute.exec_command_live(
cmd,
source_erplibre=False,
single_source_erplibre=True,
)
def generate_config_from_preconfiguration(self):
lst_choice = [
{"prompt_description": "base"},
{"prompt_description": "base + code_generator"},
{"prompt_description": "base + image_db"},
{"prompt_description": "all"},
# {"prompt_description": "base + migration"},
]
help_info = self.fill_help_info(lst_choice)
while True:
status = click.prompt(help_info)
print()
if status == "0":
return False
elif status == "1":
group = "base"
str_group = f"--group {group}"
self.generate_config(add_arg=str_group)
elif status == "2":
group = "base,code_generator"
str_group = f"--group {group}"
self.generate_config(add_arg=str_group)
elif status == "3":
group = "base,image_db"
str_group = f"--group {group}"
self.generate_config(add_arg=str_group)
elif status == "4":
self.generate_config()
# elif status == "5":
# group = "base,migration"
# str_group = f"--group {group}"
# self.generate_config(add_arg=str_group)
else:
print("Commande non trouvée 🤖!")
def generate_config_from_backup(self):
file_name = self.open_file_image_db()
add_arg = f"--from_backup_name {file_name} --add_repo odoo18.0/addons/MathBenTech_development"
self.generate_config(add_arg=add_arg)
def generate_config_from_database(self):
database_name = self.select_database()
str_arg = f"--database {database_name}"
self.generate_config(add_arg=str_arg)
return False
def select_database(self):
cmd_server = f"./odoo_bin.sh db --list"
status, lst_database = self.execute.exec_command_live(
cmd_server,
return_status_and_output=True,
source_erplibre=False,
single_source_erplibre=True,
)
lst_choice = [{"prompt_description": a.strip()} for a in lst_database]
help_info = self.fill_help_info(lst_choice)
lst_str_choice = [str(a) for a in range(len(lst_choice) + 1) if a]
while True:
status = click.prompt(help_info)
print()
if status == "0":
return False
elif status in lst_str_choice:
database_name = lst_database[int(status) - 1].strip()
print(database_name)
return database_name
else:
print("Commande non trouvée 🤖!")
def get_odoo_version(self):
with open(VERSION_DATA_FILE) as txt:
data_version = json.load(txt)
@ -776,13 +883,13 @@ class TODO:
# f'parallel ::: "./run.sh -d {bd}" "sleep'
# f' 3;./script/selenium/web_login.py{extra_cmd_web_login}"'
# )
# self.executer_commande_live(cmd)
# self.execute.exec_command_live(cmd)
cmd_server = f"./run.sh -d {bd};bash"
self.executer_commande_live(cmd_server)
self.execute.exec_command_live(cmd_server)
cmd_client = (
f"sleep 3;./script/selenium/web_login.py{extra_cmd_web_login};bash"
)
self.executer_commande_live(cmd_client)
self.execute.exec_command_live(cmd_client)
def prompt_execute_selenium(self, command=None, extra_cmd_web_login=""):
lst_cmd = []
@ -798,132 +905,12 @@ class TODO:
lst_cmd.append(cmd + extra_cmd_web_login)
if len(lst_cmd) == 1:
self.executer_commande_live(lst_cmd[0])
self.execute.exec_command_live(lst_cmd[0])
elif len(lst_cmd) > 1:
new_cmd = "parallel ::: "
for i, cmd in enumerate(lst_cmd):
new_cmd += f' "sleep {1 * i};{cmd}"'
self.executer_commande_live(new_cmd)
def executer_commande_live(
self,
commande,
source_erplibre=True,
quiet=False,
single_source_erplibre=False,
new_window=False,
single_source_odoo=False,
source_odoo="",
new_env=None,
return_status_and_command=False,
return_status_and_output=False,
return_status_and_output_and_command=False,
):
"""
Exécute une commande et affiche la sortie en direct.
Args:
commande (str): La commande à exécuter (sous forme de chaîne de caractères).
"""
my_env = os.environ.copy()
if new_env:
my_env.update(new_env)
process_start_time = time.time()
return_status = None
if source_erplibre:
# commande = f"source ./{cst_venv_erplibre}/bin/activate && " + commande
# cmd = (
# f"gnome-terminal --tab -- bash -c 'source"
# f" ./{cst_venv_erplibre}/bin/activate;{commande}'"
# )
commande = self.cmd_source_erplibre % commande
# os.system(f"./script/terminal/open_terminal.sh {commande}")
elif single_source_erplibre:
commande = (
f"source ./{cst_venv_erplibre}/bin/activate && %s" % commande
)
elif single_source_odoo:
if not source_odoo and os.path.exists("./.erplibre-version"):
with open("./.erplibre-version") as f:
source_odoo = f.read()
if not source_odoo:
_logger.error(
f"You cannot execute Odoo command if no version is installed. Command : {commande}"
)
return -1
commande = (
f"source ./.venv.{source_odoo}/bin/activate && {commande}"
)
elif new_window and self.cmd_source_default:
commande = self.cmd_source_default % commande
print("🏠 ⬇ Execute command :")
print(commande)
lst_output = []
try:
process = subprocess.Popen(
commande,
shell=True,
executable="/bin/bash",
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1, # Désactive la mise en tampon pour la sortie en direct
universal_newlines=True, # Pour traiter les sauts de lignes correctement
env=my_env,
)
while True:
ligne = process.stdout.readline()
if not ligne:
break
print(ligne, end="")
if (
return_status_and_output
or return_status_and_output_and_command
):
lst_output.append(ligne)
process.wait() # Attendre la fin du process
return_status = process.returncode
if process.returncode != 0 and not quiet:
print(
"La commande a retourné un code d'erreur :"
f" {process.returncode}"
)
except FileNotFoundError:
if "password" in commande:
print(
f"Erreur : La commande '{commande.split(' ')[0]}'[...] n'a"
" pas été trouvée."
)
else:
print(
f"Erreur : La commande '{commande}' n'a pas été trouvée."
)
except Exception as e:
print(f"Une erreur s'est produite : {e}")
process_end_time = time.time()
duration_sec = process_end_time - process_start_time
if humanize:
duration_delta = datetime.timedelta(seconds=duration_sec)
humain_time = humanize.precisedelta(duration_delta)
print(f"🏠 ⬆ Executed ({humain_time}) :")
else:
print(f"🏠 ⬆ Executed ({duration_sec:.2f} sec.) :")
print(commande)
print()
if return_status_and_output_and_command:
return return_status, commande, lst_output
if return_status_and_command:
return return_status, commande
if return_status_and_output:
return return_status, lst_output
return return_status
self.execute.exec_command_live(new_cmd)
def crash_diagnostic(self, e):
# TODO show message at start if os.path.exists(file_error_path)
@ -948,7 +935,7 @@ class TODO:
time.sleep(0.5)
cmd = "./script/todo/source_todo.sh"
# self.restart_script(e)
self.executer_commande_live(cmd, source_erplibre=True)
self.execute.exec_command_live(cmd, source_erplibre=True)
sys.exit(1)
if os.path.exists(cst_venv_erplibre):
print("Import error : ")
@ -980,19 +967,30 @@ class TODO:
from pykeepass import PyKeePass
except ImportError:
print("Rerun and exit")
self.executer_commande_live(cmd, source_erplibre=True)
self.execute.exec_command_live(cmd, source_erplibre=True)
sys.exit(1)
print("No error")
else:
self.prompt_install()
def open_shell_on_database(self):
database = self.select_database()
cmd_server = f"./odoo_bin.sh shell -d {database}"
status, lst_database = self.execute.exec_command_live(
cmd_server,
return_status_and_output=True,
source_erplibre=False,
single_source_erplibre=True,
new_window=True,
)
def upgrade_module(self):
upgrade = todo_upgrade.TodoUpgrade(self)
upgrade.execute_module_upgrade()
def upgrade_poetry(self):
# Only show the version to the user
status = self.executer_commande_live(
status = self.execute.exec_command_live(
f"make version",
source_erplibre=False,
)
@ -1001,7 +999,7 @@ class TODO:
"💬 Would you like to fetch all your git repositories, you need it (y/Y) : "
)
if git_repo_update_input.strip().lower() == "y":
status = self.executer_commande_live(
status = self.execute.exec_command_live(
f"./script/manifest/update_manifest_local_dev.sh",
source_erplibre=False,
)
@ -1022,7 +1020,7 @@ class TODO:
except Exception as e:
pass
status = self.executer_commande_live(
status = self.execute.exec_command_live(
f"pip install -r requirement/erplibre_require-ments-poetry.txt && "
f"./script/poetry/poetry_update.py -f",
source_erplibre=False,
@ -1042,20 +1040,13 @@ class TODO:
if status == "1":
file_name = status
else:
self.dir_path = ""
file_browser = todo_file_browser.FileBrowser(
path_image_db, self.on_dir_selected
)
file_browser.run_main_frame()
file_name = os.path.basename(self.dir_path)
print(file_name)
file_name = self.open_file_image_db
database_name = input("💬 Database name : ")
if not database_name:
_logger.error("Missing database name")
return
status, lst_output = self.executer_commande_live(
status, lst_output = self.execute.exec_command_live(
f"python3 ./script/database/db_restore.py -d {database_name} --ignore_cache --image {file_name}",
return_status_and_output=True,
single_source_erplibre=True,
@ -1067,7 +1058,7 @@ class TODO:
.lower()
)
if status == "y":
status, lst_output = self.executer_commande_live(
status, lst_output = self.execute.exec_command_live(
f"./script/addons/update_prod_to_dev.sh {database_name}",
return_status_and_output=True,
single_source_erplibre=True,
@ -1079,19 +1070,32 @@ class TODO:
.lower()
)
if status == "y":
status, lst_output = self.executer_commande_live(
status, lst_output = self.execute.exec_command_live(
f"./script/addons/update_addons_all.sh {database_name}",
return_status_and_output=True,
single_source_erplibre=True,
source_erplibre=False,
)
def open_file_image_db(self):
self.dir_path = ""
path_image_db = os.path.join(os.getcwd(), "image_db")
# self.dir_path is over-write into on_dir_selected
file_browser = todo_file_browser.FileBrowser(
path_image_db, self.on_dir_selected
)
file_browser.run_main_frame()
file_name = os.path.basename(self.dir_path)
print(file_name)
return file_name
def process_kill_from_port(self):
cfg = configparser.ConfigParser()
cfg.read("./config.conf")
http_port = cfg.getint("options", "http_port")
status = self.executer_commande_live(
status = self.execute.exec_command_live(
f"./script/process/kill_process_by_port.py {http_port} --kill-tree --nb_parent 2",
source_erplibre=False,
)
@ -1099,7 +1103,7 @@ class TODO:
def download_database_backup_cli(self, show_remote_list=True):
database_domain = input("Domain Odoo (ex. https://mondomain.com) : ")
if show_remote_list:
status, lst_output = self.executer_commande_live(
status, lst_output = self.execute.exec_command_live(
f"python3 ./script/database/list_remote.py --raw --odoo-url {database_domain}",
return_status_and_output=True,
single_source_erplibre=True,
@ -1134,7 +1138,7 @@ class TODO:
my_env["DATABASE_NAME"] = database_name
my_env["OUTPUT_FILE_PATH"] = output_path
my_env["ODOO_URL"] = database_domain
status, cmd_executed = self.executer_commande_live(
status, cmd_executed = self.execute.exec_command_live(
cmd,
source_erplibre=False,
return_status_and_command=True,
@ -1265,7 +1269,7 @@ class TODO:
# Rename with script bash
cmd_client = f'cd {MOBILE_HOME_PATH} && npx cap init "{project_name}" "{package_name}" && ./rename_android.sh "{project_name}" "{package_name}" && npx cap sync android'
self.executer_commande_live(cmd_client, source_erplibre=False)
self.execute.exec_command_live(cmd_client, source_erplibre=False)
# dotenv_mobile = dotenv.dotenv_values(dotenv_file)
# dotenv_mobile["VITE_TITLE"] = project_name
@ -1293,7 +1297,7 @@ class TODO:
)
if do_change_picture_menu:
status = self.executer_commande_live(
status = self.execute.exec_command_live(
f"cd {MOBILE_HOME_PATH} && npx cap open android;bash",
source_erplibre=False,
new_window=True,
@ -1305,11 +1309,11 @@ class TODO:
"Did you finish to update image with Android-Studio ? Press to continue ..."
)
cmd_client = "cp ./mobile/erplibre_home_mobile/android/app/src/main/ic_launcher-playstore.png ./mobile/erplibre_home_mobile/src/assets/company_logo.png"
self.executer_commande_live(cmd_client, source_erplibre=False)
self.execute.exec_command_live(cmd_client, source_erplibre=False)
cmd_client = "cp ./mobile/erplibre_home_mobile/android/app/src/main/ic_launcher-playstore.png ./mobile/erplibre_home_mobile/src/assets/imgs/logo.png"
self.executer_commande_live(cmd_client, source_erplibre=False)
self.execute.exec_command_live(cmd_client, source_erplibre=False)
status = self.executer_commande_live(
status = self.execute.exec_command_live(
"./mobile/compile_and_run.sh", source_erplibre=False
)

View file

@ -19,6 +19,7 @@ new_path = os.path.normpath(
)
sys.path.append(new_path)
from script.execute import execute
from script.git.git_tool import GitTool
_logger = logging.getLogger(__name__)
@ -52,6 +53,7 @@ class TodoUpgrade:
self.lst_command_executed = []
self.dct_module_per_version = {}
self.dct_module_per_dct_version_path = {}
self.execute = execute.Execute()
def write_config(self):
if "date_create" not in self.dct_progression.keys():
@ -1857,7 +1859,7 @@ class TodoUpgrade:
get_output = True
output = None
if get_output:
status, cmd_executed, output = self.todo.executer_commande_live(
status, cmd_executed, output = self.execute.exec_command_live(
cmd,
source_erplibre=False,
single_source_odoo=single_source_odoo,
@ -1866,7 +1868,7 @@ class TodoUpgrade:
quiet=quiet,
)
else:
status, cmd_executed = self.todo.executer_commande_live(
status, cmd_executed = self.execute.exec_command_live(
cmd,
source_erplibre=False,
single_source_odoo=single_source_odoo,