2020-06-22 22:36:54 -04:00
|
|
|
|
. ./env_var.sh
|
2020-07-24 02:20:30 -04:00
|
|
|
|
EL_USER=${USER}
|
2020-06-22 22:36:54 -04:00
|
|
|
|
EL_HOME=$PWD
|
2025-05-05 04:43:13 -04:00
|
|
|
|
EL_HOME_ODOO="${EL_HOME}/odoo${EL_ODOO_VERSION}/odoo"
|
2020-06-22 22:36:54 -04:00
|
|
|
|
#EL_INSTALL_WKHTMLTOPDF="True"
|
|
|
|
|
|
#EL_PORT="8069"
|
|
|
|
|
|
#EL_LONGPOLLING_PORT="8072"
|
|
|
|
|
|
#EL_SUPERADMIN="admin"
|
2021-07-21 16:20:25 -04:00
|
|
|
|
#EL_CONFIG_FILE="${EL_HOME}/config.conf"
|
2020-06-22 22:36:54 -04:00
|
|
|
|
#EL_CONFIG="${EL_USER}"
|
|
|
|
|
|
#EL_MINIMAL_ADDONS="False"
|
|
|
|
|
|
#EL_INSTALL_NGINX="True"
|
2025-05-05 04:43:13 -04:00
|
|
|
|
FILE_INSTALLATION_VERSION=".repo/installed_odoo_version.txt"
|
2020-06-22 22:36:54 -04:00
|
|
|
|
|
2024-02-23 13:01:10 -05:00
|
|
|
|
Red='\033[0;31m' # Red
|
|
|
|
|
|
Color_Off='\033[0m' # Text Reset
|
|
|
|
|
|
|
2024-08-25 15:54:24 -04:00
|
|
|
|
# example, 3.7.8 will be 3.7 into PYTHON_VERSION_MAJOR
|
2025-05-05 04:43:13 -04:00
|
|
|
|
PYTHON_VERSION_MAJOR=$(echo "$EL_PYTHON_ODOO_VERSION" | sed 's/\.[^\.]*$//')
|
|
|
|
|
|
VENV_ERPLIBRE_PATH=$(cat "conf/python-erplibre-venv" | xargs)
|
|
|
|
|
|
VENV_ODOO_PATH=".venv.${EL_ERPLIBRE_VERSION}"
|
[ADD] install: uv to place Python packages, pip as fallback
uv replaces pip where it can: the tools venv and the Poetry bootstrap. The
choice lives in EL_PIP_PROVIDER -- auto, uv or pip -- and in a single
file, lib_pip_provider.sh, on the exact model of the mise/pyenv switch. A
uv failure falls back to pip: it is stricter on metadata and rejects
packages pip accepts.
Three guards. The target always goes through "--python" rather than being
inferred from the active venv: poetry.toml declares a "./.venv" uv would
also look for. Python 3.7, still used by Odoo 12 and 13, stays on pip. And
"uv pip sync" is never used: it would delete pip itself and everything
Poetry laid down.
One bug falls along the way: the idempotence guard aimed at
.venv.erplibre/bin/poetry while Poetry installs into the Odoo venv, so a
successful replay reported failure all the same.
--- FR ---
uv remplace pip là où il le peut : le venv d'outils et l'amorçage de
Poetry. Le choix vit dans EL_PIP_PROVIDER — auto, uv ou pip — et dans un
seul fichier, lib_pip_provider.sh, sur le modèle exact de l'aiguillage
mise/pyenv. Un échec d'uv retombe sur pip : il est plus strict sur les
métadonnées et refuse des paquets que pip accepte.
Trois gardes. La cible passe toujours par « --python » plutôt que d'être
déduite du venv actif : poetry.toml déclare un « ./.venv » qu'uv
chercherait aussi. Python 3.7, encore utilisé par Odoo 12 et 13, reste sur
pip. Et « uv pip sync » n'est jamais employé : il supprimerait pip
lui-même et tout ce que Poetry a posé.
Un défaut tombe au passage : le garde d'idempotence visait
.venv.erplibre/bin/poetry alors que Poetry s'installe dans le venv Odoo,
si bien qu'un rejeu réussi rapportait quand même un échec.
Assisted-by: Claude Opus 5
2026-08-11 23:16:26 -04:00
|
|
|
|
# Poetry est installé dans le venv ODOO, pas dans celui des outils : le garde
|
|
|
|
|
|
# d'idempotence visait le mauvais chemin, donc il était TOUJOURS vrai. Sans
|
|
|
|
|
|
# conséquence visible — poetry se réinstallait pour rien — mais le jour où ce
|
|
|
|
|
|
# fichier aurait existé, « poetry install » aurait été purement sauté.
|
|
|
|
|
|
POETRY_ODOO_PATH=${VENV_ODOO_PATH}/bin/poetry
|
|
|
|
|
|
|
|
|
|
|
|
# Choix pip/uv : un seul endroit décide, comme pour mise/pyenv.
|
|
|
|
|
|
# shellcheck source=script/install/lib_pip_provider.sh
|
|
|
|
|
|
. ./script/install/lib_pip_provider.sh
|
[FIX] install s390x: the compiler was killed for lack of memory
matplotlib dies on "c++: fatal error: Killed signal terminated program
cc1plus". "Killed" is a SIGKILL: the kernel's OOM killer, and nothing in
the message names memory. A single matplotlib source file asks cc1plus
for up to 2.5 GiB.
Two causes compound. The VM is small -- the catalogue starts at 1 or
2 GiB -- and every build backend launches nproc compilations in
parallel, each with its own cc1plus. Six cores exhaust 8 GiB.
Hence two answers. A swap file tops memory up to 8 GiB, never taking
more than half the free disk nor touching fstab -- a declared and
missing swap degrades boot. And parallelism is bounded by actual
memory, 2 GiB per task.
ninja has no parallelism environment variable, but meson-python reads
"NINJA", the executable PATH -- verified in mesonpy 0.20. We point it at
a wrapper that adds the -j. That is what saves matplotlib; MAKEFLAGS and
CMAKE_BUILD_PARALLEL_LEVEL cover the rest.
--- FR ---
matplotlib s'arrête sur « c++: fatal error: Killed signal terminated
program cc1plus ». « Killed » est un SIGKILL : c'est le tueur du noyau,
et rien dans le message ne nomme la mémoire. Un seul fichier de
matplotlib demande jusqu'à 2,5 Gio à cc1plus.
Deux causes se cumulent. La VM est petite — le catalogue démarre à 1 ou
2 Gio — et chaque moteur de build lance nproc compilations en parallèle,
chacune avec son cc1plus. Six cœurs épuisent 8 Gio.
D'où deux réponses. Un fichier d'échange complète la mémoire jusqu'à
8 Gio, sans jamais prendre plus de la moitié du disque libre ni toucher
à fstab — un swap déclaré et disparu dégrade le démarrage. Et le
parallélisme est borné d'après la mémoire réelle, 2 Gio par tâche.
ninja n'a aucune variable de parallélisme, mais meson-python lit
« NINJA », le CHEMIN de l'exécutable — vérifié dans mesonpy 0.20. On y
met une enveloppe qui ajoute le -j. C'est ce qui sauve matplotlib ;
MAKEFLAGS et CMAKE_BUILD_PARALLEL_LEVEL couvrent les autres.
Assisted-by: Claude Opus 5
2026-08-12 02:56:18 -04:00
|
|
|
|
# Bornage des compilations : voir el_build_limit_jobs.
|
|
|
|
|
|
. ./script/install/lib_lowmem.sh
|
2025-07-14 03:44:48 -04:00
|
|
|
|
export WITH_POETRY_INSTALLATION=1
|
2020-07-29 18:13:22 -04:00
|
|
|
|
|
[ADD] install: uv to place Python packages, pip as fallback
uv replaces pip where it can: the tools venv and the Poetry bootstrap. The
choice lives in EL_PIP_PROVIDER -- auto, uv or pip -- and in a single
file, lib_pip_provider.sh, on the exact model of the mise/pyenv switch. A
uv failure falls back to pip: it is stricter on metadata and rejects
packages pip accepts.
Three guards. The target always goes through "--python" rather than being
inferred from the active venv: poetry.toml declares a "./.venv" uv would
also look for. Python 3.7, still used by Odoo 12 and 13, stays on pip. And
"uv pip sync" is never used: it would delete pip itself and everything
Poetry laid down.
One bug falls along the way: the idempotence guard aimed at
.venv.erplibre/bin/poetry while Poetry installs into the Odoo venv, so a
successful replay reported failure all the same.
--- FR ---
uv remplace pip là où il le peut : le venv d'outils et l'amorçage de
Poetry. Le choix vit dans EL_PIP_PROVIDER — auto, uv ou pip — et dans un
seul fichier, lib_pip_provider.sh, sur le modèle exact de l'aiguillage
mise/pyenv. Un échec d'uv retombe sur pip : il est plus strict sur les
métadonnées et refuse des paquets que pip accepte.
Trois gardes. La cible passe toujours par « --python » plutôt que d'être
déduite du venv actif : poetry.toml déclare un « ./.venv » qu'uv
chercherait aussi. Python 3.7, encore utilisé par Odoo 12 et 13, reste sur
pip. Et « uv pip sync » n'est jamais employé : il supprimerait pip
lui-même et tout ce que Poetry a posé.
Un défaut tombe au passage : le garde d'idempotence visait
.venv.erplibre/bin/poetry alors que Poetry s'installe dans le venv Odoo,
si bien qu'un rejeu réussi rapportait quand même un échec.
Assisted-by: Claude Opus 5
2026-08-11 23:16:26 -04:00
|
|
|
|
# Verbosité de l'installation Poetry. « -q » a été retiré du défaut : dans Cleo,
|
|
|
|
|
|
# le mode silencieux coupe AUSSI la sortie d'erreur. Mesuré — « poetry -q
|
|
|
|
|
|
# commande-inexistante » rend 1 sans imprimer un caractère, quand la même sans
|
|
|
|
|
|
# « -q » nomme le problème. Un échec devenait donc parfaitement muet, et c'est
|
|
|
|
|
|
# pour cela qu'il avait fallu ajouter un rejeu de diagnostic plus bas.
|
|
|
|
|
|
# La verbosité par défaut de Poetry tient en une ligne par paquet.
|
2026-07-27 23:57:04 -04:00
|
|
|
|
if [[ "${EL_VERBOSE:-0}" == "1" ]]; then
|
|
|
|
|
|
POETRY_VERBOSE="-vvv"
|
|
|
|
|
|
else
|
[ADD] install: uv to place Python packages, pip as fallback
uv replaces pip where it can: the tools venv and the Poetry bootstrap. The
choice lives in EL_PIP_PROVIDER -- auto, uv or pip -- and in a single
file, lib_pip_provider.sh, on the exact model of the mise/pyenv switch. A
uv failure falls back to pip: it is stricter on metadata and rejects
packages pip accepts.
Three guards. The target always goes through "--python" rather than being
inferred from the active venv: poetry.toml declares a "./.venv" uv would
also look for. Python 3.7, still used by Odoo 12 and 13, stays on pip. And
"uv pip sync" is never used: it would delete pip itself and everything
Poetry laid down.
One bug falls along the way: the idempotence guard aimed at
.venv.erplibre/bin/poetry while Poetry installs into the Odoo venv, so a
successful replay reported failure all the same.
--- FR ---
uv remplace pip là où il le peut : le venv d'outils et l'amorçage de
Poetry. Le choix vit dans EL_PIP_PROVIDER — auto, uv ou pip — et dans un
seul fichier, lib_pip_provider.sh, sur le modèle exact de l'aiguillage
mise/pyenv. Un échec d'uv retombe sur pip : il est plus strict sur les
métadonnées et refuse des paquets que pip accepte.
Trois gardes. La cible passe toujours par « --python » plutôt que d'être
déduite du venv actif : poetry.toml déclare un « ./.venv » qu'uv
chercherait aussi. Python 3.7, encore utilisé par Odoo 12 et 13, reste sur
pip. Et « uv pip sync » n'est jamais employé : il supprimerait pip
lui-même et tout ce que Poetry a posé.
Un défaut tombe au passage : le garde d'idempotence visait
.venv.erplibre/bin/poetry alors que Poetry s'installe dans le venv Odoo,
si bien qu'un rejeu réussi rapportait quand même un échec.
Assisted-by: Claude Opus 5
2026-08-11 23:16:26 -04:00
|
|
|
|
POETRY_VERBOSE=""
|
2026-07-27 23:57:04 -04:00
|
|
|
|
fi
|
|
|
|
|
|
|
2026-03-30 22:08:00 -04:00
|
|
|
|
# EL_PHASE controls which steps to execute. Used by install_locally_dev.sh
|
|
|
|
|
|
# for parallel installation — do not set manually unless you know what you do.
|
|
|
|
|
|
# all (default) – full install: setup + poetry phases
|
|
|
|
|
|
# setup – prereqs only: venvs, pip-erplibre, git-repo
|
|
|
|
|
|
# poetry – python packages: poetry install + post-install
|
|
|
|
|
|
EL_PHASE=${EL_PHASE:-all}
|
|
|
|
|
|
|
|
|
|
|
|
# ── Setup phase (venvs + pip-erplibre + git-repo) ────────────────────────────
|
|
|
|
|
|
if [[ "${EL_PHASE}" != "poetry" ]]; then
|
|
|
|
|
|
./script/generate_config.sh
|
|
|
|
|
|
|
|
|
|
|
|
# Generate empty addons if missing
|
|
|
|
|
|
path_addons_addons="./odoo${EL_ODOO_VERSION}/addons/addons"
|
|
|
|
|
|
if [[ ! -d "${path_addons_addons}" ]]; then
|
|
|
|
|
|
mkdir -p "${path_addons_addons}"
|
|
|
|
|
|
fi
|
2020-07-24 02:20:30 -04:00
|
|
|
|
|
2026-03-30 22:08:00 -04:00
|
|
|
|
if [[ ! -n "${DOCKER_BUILD}" ]]; then
|
|
|
|
|
|
# Install ERPLibre venv
|
|
|
|
|
|
echo -e "Install ${VENV_ERPLIBRE_PATH} with ${EL_PYTHON_ERPLIBRE_VERSION}"
|
[ADD] install: mise as Python provider, pyenv as fallback
mise lays down a precompiled CPython where pyenv builds one: seconds
against one to three minutes, with no -dev package at all. The choice
lives in EL_PYTHON_PROVIDER -- auto, mise or pyenv -- and in a single
file, lib_python_provider.sh. The rest of the repository only knows venv
paths and needs to know none of this.
In auto mode an ALREADY installed interpreter wins, whichever provider put
it there. mise is never installed on its own, "curl | sh" commits too much
for a script to decide -- make install_mise carries that decision.
MISE_PYTHON_COMPILE=false forbids it from quietly compiling: without that
guard it would fall back to pyenv's own engine, giving us the slowness
without the tooling. That is also what stopped gcc from collapsing while
building CPython on a low-memory s390x guest, for nothing.
One real bug falls along the way: a failed venv did not stop the install,
which then went on and failed further down, far from the cause.
--- FR ---
mise pose un CPython précompilé là où pyenv en compile un : des secondes
contre une à trois minutes, et aucun paquet -dev. Le choix vit dans
EL_PYTHON_PROVIDER — auto, mise ou pyenv — et dans un seul fichier,
lib_python_provider.sh. Le reste du dépôt ne connaît que des chemins de
venv et n'a rien à savoir de tout cela.
En mode auto, un interpréteur DÉJÀ posé l'emporte, quel qu'en soit le
fournisseur. mise n'est jamais installé de lui-même, « curl | sh » engage
trop pour qu'un script en décide — make install_mise porte cette décision.
MISE_PYTHON_COMPILE=false lui interdit de compiler en silence : sans ce
garde, il retomberait sur le moteur de pyenv, et nous aurions sa lenteur
sans son outillage. C'est aussi ce qui a évité que gcc s'écroule en
bâtissant CPython sur une VM s390x à faible mémoire, inutilement.
Un vrai défaut tombe au passage : un venv raté n'arrêtait pas
l'installation, qui continuait et échouait plus loin, loin de la cause.
Assisted-by: Claude Opus 5
2026-08-11 22:03:40 -04:00
|
|
|
|
# Le code de retour n'était PAS regardé : quand l'interpréteur ne
|
|
|
|
|
|
# pouvait pas être obtenu, le script continuait, et tout ce qui suit
|
|
|
|
|
|
# échouait à son tour sur un venv inexistant. Le log devenait une
|
|
|
|
|
|
# cascade de « No such file or directory » répartie sur trois fichiers,
|
|
|
|
|
|
# où la cause réelle — pas de compilateur C — se perdait tout en haut.
|
|
|
|
|
|
if ! ./script/install/install_venv.sh "ERPLibre" "${VENV_ERPLIBRE_PATH}" "${EL_PYTHON_ERPLIBRE_VERSION}"; then
|
|
|
|
|
|
echo "Echec de creation de ${VENV_ERPLIBRE_PATH}, arret."
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
2026-03-30 22:08:00 -04:00
|
|
|
|
# Install Odoo venv
|
|
|
|
|
|
echo -e "Install ${VENV_ODOO_PATH} with ${EL_PYTHON_ODOO_VERSION}"
|
[ADD] install: mise as Python provider, pyenv as fallback
mise lays down a precompiled CPython where pyenv builds one: seconds
against one to three minutes, with no -dev package at all. The choice
lives in EL_PYTHON_PROVIDER -- auto, mise or pyenv -- and in a single
file, lib_python_provider.sh. The rest of the repository only knows venv
paths and needs to know none of this.
In auto mode an ALREADY installed interpreter wins, whichever provider put
it there. mise is never installed on its own, "curl | sh" commits too much
for a script to decide -- make install_mise carries that decision.
MISE_PYTHON_COMPILE=false forbids it from quietly compiling: without that
guard it would fall back to pyenv's own engine, giving us the slowness
without the tooling. That is also what stopped gcc from collapsing while
building CPython on a low-memory s390x guest, for nothing.
One real bug falls along the way: a failed venv did not stop the install,
which then went on and failed further down, far from the cause.
--- FR ---
mise pose un CPython précompilé là où pyenv en compile un : des secondes
contre une à trois minutes, et aucun paquet -dev. Le choix vit dans
EL_PYTHON_PROVIDER — auto, mise ou pyenv — et dans un seul fichier,
lib_python_provider.sh. Le reste du dépôt ne connaît que des chemins de
venv et n'a rien à savoir de tout cela.
En mode auto, un interpréteur DÉJÀ posé l'emporte, quel qu'en soit le
fournisseur. mise n'est jamais installé de lui-même, « curl | sh » engage
trop pour qu'un script en décide — make install_mise porte cette décision.
MISE_PYTHON_COMPILE=false lui interdit de compiler en silence : sans ce
garde, il retomberait sur le moteur de pyenv, et nous aurions sa lenteur
sans son outillage. C'est aussi ce qui a évité que gcc s'écroule en
bâtissant CPython sur une VM s390x à faible mémoire, inutilement.
Un vrai défaut tombe au passage : un venv raté n'arrêtait pas
l'installation, qui continuait et échouait plus loin, loin de la cause.
Assisted-by: Claude Opus 5
2026-08-11 22:03:40 -04:00
|
|
|
|
if ! ./script/install/install_venv.sh "Odoo" "${VENV_ODOO_PATH}" "${EL_PYTHON_ODOO_VERSION}"; then
|
|
|
|
|
|
echo "Echec de creation de ${VENV_ODOO_PATH}, arret."
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
2026-03-30 22:08:00 -04:00
|
|
|
|
else
|
|
|
|
|
|
mkdir .venv
|
|
|
|
|
|
fi
|
2025-05-05 04:43:13 -04:00
|
|
|
|
|
2026-03-30 22:08:00 -04:00
|
|
|
|
source ./${VENV_ERPLIBRE_PATH}/bin/activate
|
|
|
|
|
|
echo -e "Upgrade pip to ${VENV_ERPLIBRE_PATH}"
|
|
|
|
|
|
pip install --upgrade pip
|
[ADD] install: uv to place Python packages, pip as fallback
uv replaces pip where it can: the tools venv and the Poetry bootstrap. The
choice lives in EL_PIP_PROVIDER -- auto, uv or pip -- and in a single
file, lib_pip_provider.sh, on the exact model of the mise/pyenv switch. A
uv failure falls back to pip: it is stricter on metadata and rejects
packages pip accepts.
Three guards. The target always goes through "--python" rather than being
inferred from the active venv: poetry.toml declares a "./.venv" uv would
also look for. Python 3.7, still used by Odoo 12 and 13, stays on pip. And
"uv pip sync" is never used: it would delete pip itself and everything
Poetry laid down.
One bug falls along the way: the idempotence guard aimed at
.venv.erplibre/bin/poetry while Poetry installs into the Odoo venv, so a
successful replay reported failure all the same.
--- FR ---
uv remplace pip là où il le peut : le venv d'outils et l'amorçage de
Poetry. Le choix vit dans EL_PIP_PROVIDER — auto, uv ou pip — et dans un
seul fichier, lib_pip_provider.sh, sur le modèle exact de l'aiguillage
mise/pyenv. Un échec d'uv retombe sur pip : il est plus strict sur les
métadonnées et refuse des paquets que pip accepte.
Trois gardes. La cible passe toujours par « --python » plutôt que d'être
déduite du venv actif : poetry.toml déclare un « ./.venv » qu'uv
chercherait aussi. Python 3.7, encore utilisé par Odoo 12 et 13, reste sur
pip. Et « uv pip sync » n'est jamais employé : il supprimerait pip
lui-même et tout ce que Poetry a posé.
Un défaut tombe au passage : le garde d'idempotence visait
.venv.erplibre/bin/poetry alors que Poetry s'installe dans le venv Odoo,
si bien qu'un rejeu réussi rapportait quand même un échec.
Assisted-by: Claude Opus 5
2026-08-11 23:16:26 -04:00
|
|
|
|
el_pip_install "${VENV_ERPLIBRE_PATH}" \
|
|
|
|
|
|
-r requirement/erplibre_require-ments.txt
|
2025-05-05 04:43:13 -04:00
|
|
|
|
|
2026-03-30 22:08:00 -04:00
|
|
|
|
./script/install/install_git_repo.sh
|
|
|
|
|
|
fi
|
2020-07-29 18:13:22 -04:00
|
|
|
|
|
2026-03-30 22:08:00 -04:00
|
|
|
|
# ── Poetry phase (install python packages + post-install) ────────────────────
|
|
|
|
|
|
if [[ "${EL_PHASE}" != "setup" ]]; then
|
|
|
|
|
|
source ${VENV_ODOO_PATH}/bin/activate
|
|
|
|
|
|
echo -e "Upgrade pip to ${VENV_ODOO_PATH}"
|
|
|
|
|
|
pip install --upgrade pip
|
2022-12-21 00:22:20 -05:00
|
|
|
|
|
2026-03-30 22:08:00 -04:00
|
|
|
|
echo -e "\n---- Installing poetry dependency ----"
|
2025-07-25 15:59:53 -04:00
|
|
|
|
|
2026-03-30 22:08:00 -04:00
|
|
|
|
if [[ -z "${EL_POETRY_VERSION}" ]]; then
|
|
|
|
|
|
echo -e "${Red}Error${Color_Off} missing poetry version, please check file .poetry-version"
|
|
|
|
|
|
cat .poetry-version
|
|
|
|
|
|
ls -la
|
2022-12-21 00:22:20 -05:00
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
2022-12-21 00:25:29 -05:00
|
|
|
|
|
[REM] install: drop Ubuntu 20.04 and 22.04
Two blockers on 20.04, neither worth carrying. "TypeError: unsupported
operand type(s) for |" fired before the install even started:
update_env_version.py imports erplibre_state as the very first thing
"make install_os" does, hence before pyenv, on the system Python 3.8,
where a "str | None" annotation is evaluated at import. And cryptography
now demands OpenSSL 3, while focal ships 1.1.1.
Annotations are therefore deferred, a contract the bootstrap file already
stated in a comment and now holds across script/version and
script/install. But the releases themselves go: pikepdf requires
qpdf >= 12.2, compiled in C++20, when focal ships GCC 9.
--- FR ---
Deux blocages sur 20.04, aucun ne méritant d'être porté. « TypeError:
unsupported operand type(s) for | » se déclenchait avant même le début de
l'installation : update_env_version.py importe erplibre_state en tout
premier lieu de « make install_os », donc avant pyenv, sur le Python 3.8
du système, où une annotation « str | None » est évaluée à l'import. Et
cryptography exige désormais OpenSSL 3, quand focal livre 1.1.1.
Les annotations sont donc différées, contrat que le fichier d'amorçage
énonçait déjà en commentaire et qui tient maintenant sur script/version et
script/install. Mais les versions elles-mêmes partent : pikepdf réclame
qpdf >= 12.2, compilé en C++20, quand focal livre GCC 9.
Assisted-by: Claude Opus 5
2026-08-11 08:03:32 -04:00
|
|
|
|
# s390x UNIQUEMENT — la borne ci-dessous ne doit toucher aucune autre
|
|
|
|
|
|
# architecture, et le test d'architecture vient donc en premier.
|
|
|
|
|
|
#
|
|
|
|
|
|
# Poetry tire keyring, donc SecretStorage, donc cryptography, dont la
|
|
|
|
|
|
# DERNIÈRE version : rien ne la borne à cette étape. Partout ailleurs c'est
|
|
|
|
|
|
# sans conséquence, pip y pose une roue manylinux qui embarque son propre
|
|
|
|
|
|
# OpenSSL en statique — vérifié, la 50.0.0 en publie pour x86_64, aarch64,
|
|
|
|
|
|
# ppc64le et armv7l. s390x est la SEULE sans roue : elle compile, contre
|
|
|
|
|
|
# l'OpenSSL du système.
|
|
|
|
|
|
#
|
|
|
|
|
|
# Or cryptography 47 a retiré le support d'OpenSSL 1.1.1 — vérifié version
|
|
|
|
|
|
# par version, les gardes « CRYPTOGRAPHY_OPENSSL_300_OR_GREATER » de
|
|
|
|
|
|
# fips.rs disparaissent entre la 46 et la 47 — et Ubuntu 20.04 livre
|
|
|
|
|
|
# 1.1.1f. D'où « EVP_default_properties_is_fips_enabled not found in ffi ».
|
|
|
|
|
|
# Sur s390x en 22.04 et au-delà, OpenSSL est en 3.x : aucune borne.
|
|
|
|
|
|
PIP_CONSTRAINT_CRYPTO=""
|
|
|
|
|
|
if [[ "$(uname -m)" == "s390x" ]]; then
|
|
|
|
|
|
OPENSSL_VER="$(pkg-config --modversion openssl 2>/dev/null \
|
|
|
|
|
|
|| openssl version 2>/dev/null | awk '{print $2}')"
|
|
|
|
|
|
case "${OPENSSL_VER}" in
|
|
|
|
|
|
3.* | 4.*) ;;
|
|
|
|
|
|
"") echo "s390x : version d'OpenSSL indeterminee, aucune borne." ;;
|
|
|
|
|
|
*)
|
|
|
|
|
|
echo "s390x, OpenSSL ${OPENSSL_VER} < 3 : cryptography borne a <47 pour poetry."
|
|
|
|
|
|
PIP_CONSTRAINT_CRYPTO="cryptography<47"
|
|
|
|
|
|
;;
|
|
|
|
|
|
esac
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
[ADD] install: uv to place Python packages, pip as fallback
uv replaces pip where it can: the tools venv and the Poetry bootstrap. The
choice lives in EL_PIP_PROVIDER -- auto, uv or pip -- and in a single
file, lib_pip_provider.sh, on the exact model of the mise/pyenv switch. A
uv failure falls back to pip: it is stricter on metadata and rejects
packages pip accepts.
Three guards. The target always goes through "--python" rather than being
inferred from the active venv: poetry.toml declares a "./.venv" uv would
also look for. Python 3.7, still used by Odoo 12 and 13, stays on pip. And
"uv pip sync" is never used: it would delete pip itself and everything
Poetry laid down.
One bug falls along the way: the idempotence guard aimed at
.venv.erplibre/bin/poetry while Poetry installs into the Odoo venv, so a
successful replay reported failure all the same.
--- FR ---
uv remplace pip là où il le peut : le venv d'outils et l'amorçage de
Poetry. Le choix vit dans EL_PIP_PROVIDER — auto, uv ou pip — et dans un
seul fichier, lib_pip_provider.sh, sur le modèle exact de l'aiguillage
mise/pyenv. Un échec d'uv retombe sur pip : il est plus strict sur les
métadonnées et refuse des paquets que pip accepte.
Trois gardes. La cible passe toujours par « --python » plutôt que d'être
déduite du venv actif : poetry.toml déclare un « ./.venv » qu'uv
chercherait aussi. Python 3.7, encore utilisé par Odoo 12 et 13, reste sur
pip. Et « uv pip sync » n'est jamais employé : il supprimerait pip
lui-même et tout ce que Poetry a posé.
Un défaut tombe au passage : le garde d'idempotence visait
.venv.erplibre/bin/poetry alors que Poetry s'installe dans le venv Odoo,
si bien qu'un rejeu réussi rapportait quand même un échec.
Assisted-by: Claude Opus 5
2026-08-11 23:16:26 -04:00
|
|
|
|
# Le garde ne couvre QUE l'amorçage de Poetry. « poetry install » doit
|
|
|
|
|
|
# rejouer à chaque fois : c'est lui qui applique un lock régénéré par
|
|
|
|
|
|
# « make poetry_update ». L'englober rendrait la mise à jour sans effet
|
|
|
|
|
|
# dès la seconde installation.
|
|
|
|
|
|
if [[ ! -x "${POETRY_ODOO_PATH}" ]]; then
|
2026-03-30 22:08:00 -04:00
|
|
|
|
echo -e "Install Poetry ${POETRY_ODOO_PATH}"
|
[ADD] install: uv to place Python packages, pip as fallback
uv replaces pip where it can: the tools venv and the Poetry bootstrap. The
choice lives in EL_PIP_PROVIDER -- auto, uv or pip -- and in a single
file, lib_pip_provider.sh, on the exact model of the mise/pyenv switch. A
uv failure falls back to pip: it is stricter on metadata and rejects
packages pip accepts.
Three guards. The target always goes through "--python" rather than being
inferred from the active venv: poetry.toml declares a "./.venv" uv would
also look for. Python 3.7, still used by Odoo 12 and 13, stays on pip. And
"uv pip sync" is never used: it would delete pip itself and everything
Poetry laid down.
One bug falls along the way: the idempotence guard aimed at
.venv.erplibre/bin/poetry while Poetry installs into the Odoo venv, so a
successful replay reported failure all the same.
--- FR ---
uv remplace pip là où il le peut : le venv d'outils et l'amorçage de
Poetry. Le choix vit dans EL_PIP_PROVIDER — auto, uv ou pip — et dans un
seul fichier, lib_pip_provider.sh, sur le modèle exact de l'aiguillage
mise/pyenv. Un échec d'uv retombe sur pip : il est plus strict sur les
métadonnées et refuse des paquets que pip accepte.
Trois gardes. La cible passe toujours par « --python » plutôt que d'être
déduite du venv actif : poetry.toml déclare un « ./.venv » qu'uv
chercherait aussi. Python 3.7, encore utilisé par Odoo 12 et 13, reste sur
pip. Et « uv pip sync » n'est jamais employé : il supprimerait pip
lui-même et tout ce que Poetry a posé.
Un défaut tombe au passage : le garde d'idempotence visait
.venv.erplibre/bin/poetry alors que Poetry s'installe dans le venv Odoo,
si bien qu'un rejeu réussi rapportait quand même un échec.
Assisted-by: Claude Opus 5
2026-08-11 23:16:26 -04:00
|
|
|
|
el_pip_install "${VENV_ODOO_PATH}" \
|
|
|
|
|
|
${PIP_CONSTRAINT_CRYPTO} "poetry==${EL_POETRY_VERSION}"
|
|
|
|
|
|
fi
|
|
|
|
|
|
# Chemin EXPLICITE, jamais le « poetry » du PATH. Le script active pourtant
|
|
|
|
|
|
# le bon venv juste avant, mais poetry.toml porte « virtualenvs.create =
|
|
|
|
|
|
# false » : hors activation, Poetry installe dans l'interpréteur de BASE.
|
|
|
|
|
|
# Vérifié à la dure sur une VM — 772 paquets posés dans le CPython de mise,
|
|
|
|
|
|
# invisibles du venv qui a « include-system-site-packages = false », et
|
|
|
|
|
|
# promis à polluer tout autre venv bâti sur le même interpréteur.
|
|
|
|
|
|
if [[ ! -x "${POETRY_ODOO_PATH}" ]]; then
|
|
|
|
|
|
echo "Poetry introuvable a ${POETRY_ODOO_PATH}, arret."
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
[FIX] install s390x: the compiler was killed for lack of memory
matplotlib dies on "c++: fatal error: Killed signal terminated program
cc1plus". "Killed" is a SIGKILL: the kernel's OOM killer, and nothing in
the message names memory. A single matplotlib source file asks cc1plus
for up to 2.5 GiB.
Two causes compound. The VM is small -- the catalogue starts at 1 or
2 GiB -- and every build backend launches nproc compilations in
parallel, each with its own cc1plus. Six cores exhaust 8 GiB.
Hence two answers. A swap file tops memory up to 8 GiB, never taking
more than half the free disk nor touching fstab -- a declared and
missing swap degrades boot. And parallelism is bounded by actual
memory, 2 GiB per task.
ninja has no parallelism environment variable, but meson-python reads
"NINJA", the executable PATH -- verified in mesonpy 0.20. We point it at
a wrapper that adds the -j. That is what saves matplotlib; MAKEFLAGS and
CMAKE_BUILD_PARALLEL_LEVEL cover the rest.
--- FR ---
matplotlib s'arrête sur « c++: fatal error: Killed signal terminated
program cc1plus ». « Killed » est un SIGKILL : c'est le tueur du noyau,
et rien dans le message ne nomme la mémoire. Un seul fichier de
matplotlib demande jusqu'à 2,5 Gio à cc1plus.
Deux causes se cumulent. La VM est petite — le catalogue démarre à 1 ou
2 Gio — et chaque moteur de build lance nproc compilations en parallèle,
chacune avec son cc1plus. Six cœurs épuisent 8 Gio.
D'où deux réponses. Un fichier d'échange complète la mémoire jusqu'à
8 Gio, sans jamais prendre plus de la moitié du disque libre ni toucher
à fstab — un swap déclaré et disparu dégrade le démarrage. Et le
parallélisme est borné d'après la mémoire réelle, 2 Gio par tâche.
ninja n'a aucune variable de parallélisme, mais meson-python lit
« NINJA », le CHEMIN de l'exécutable — vérifié dans mesonpy 0.20. On y
met une enveloppe qui ajoute le -j. C'est ce qui sauve matplotlib ;
MAKEFLAGS et CMAKE_BUILD_PARALLEL_LEVEL couvrent les autres.
Assisted-by: Claude Opus 5
2026-08-12 02:56:18 -04:00
|
|
|
|
# Là où rien n'a de roue, « poetry install » COMPILE des centaines de
|
|
|
|
|
|
# paquets, et le moteur de build de chacun lance nproc tâches en
|
|
|
|
|
|
# parallèle. cc1plus demande jusqu'à 2,5 Gio pour un seul fichier de
|
|
|
|
|
|
# matplotlib : six cœurs épuisent 8 Gio, et le noyau tue le compilateur
|
|
|
|
|
|
# sans jamais nommer la mémoire. On borne d'après la mémoire disponible.
|
|
|
|
|
|
if [[ "$(uname -m)" == "s390x" ]]; then
|
|
|
|
|
|
el_build_limit_jobs
|
|
|
|
|
|
fi
|
[ADD] install: uv to place Python packages, pip as fallback
uv replaces pip where it can: the tools venv and the Poetry bootstrap. The
choice lives in EL_PIP_PROVIDER -- auto, uv or pip -- and in a single
file, lib_pip_provider.sh, on the exact model of the mise/pyenv switch. A
uv failure falls back to pip: it is stricter on metadata and rejects
packages pip accepts.
Three guards. The target always goes through "--python" rather than being
inferred from the active venv: poetry.toml declares a "./.venv" uv would
also look for. Python 3.7, still used by Odoo 12 and 13, stays on pip. And
"uv pip sync" is never used: it would delete pip itself and everything
Poetry laid down.
One bug falls along the way: the idempotence guard aimed at
.venv.erplibre/bin/poetry while Poetry installs into the Odoo venv, so a
successful replay reported failure all the same.
--- FR ---
uv remplace pip là où il le peut : le venv d'outils et l'amorçage de
Poetry. Le choix vit dans EL_PIP_PROVIDER — auto, uv ou pip — et dans un
seul fichier, lib_pip_provider.sh, sur le modèle exact de l'aiguillage
mise/pyenv. Un échec d'uv retombe sur pip : il est plus strict sur les
métadonnées et refuse des paquets que pip accepte.
Trois gardes. La cible passe toujours par « --python » plutôt que d'être
déduite du venv actif : poetry.toml déclare un « ./.venv » qu'uv
chercherait aussi. Python 3.7, encore utilisé par Odoo 12 et 13, reste sur
pip. Et « uv pip sync » n'est jamais employé : il supprimerait pip
lui-même et tout ce que Poetry a posé.
Un défaut tombe au passage : le garde d'idempotence visait
.venv.erplibre/bin/poetry alors que Poetry s'installe dans le venv Odoo,
si bien qu'un rejeu réussi rapportait quand même un échec.
Assisted-by: Claude Opus 5
2026-08-11 23:16:26 -04:00
|
|
|
|
"${POETRY_ODOO_PATH}" --version
|
|
|
|
|
|
# To fix keyring problem when installation is blocked, use
|
|
|
|
|
|
export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring
|
[FIX] install : compiler pykcs11 avec SWIG 4.3 et au-delà
Toute installation d'Odoo 14, 15 ou 17 échoue depuis que SWIG 4.5 est paru
sur PyPI : « ‘PyInt_FromLong’ was not declared in this scope », 55 fois.
pykcs11 — tiré par endesive — ne livre aucun wrapper pré-généré, et son
« requires = ["swig"] » n'est pas borné : c'est la DERNIÈRE version publiée
qui tourne, pas celle du système. Or SWIG 4.3 a retiré les alias Python 2
qu'il écrivait lui-même, et le typemap CK_RV de pykcs11 en utilise un.
On rend l'alias au préprocesseur, identique token pour token à celui de
SWIG 4.2. CPPFLAGS et non CFLAGS : un .cpp passe par compiler_so_cxx.
Vérifié sur la VM et ici : poetry install rend 0, import PyKCS11 passe.
--- EN ---
Every Odoo 14, 15 and 17 install has been failing since SWIG 4.5 landed on
PyPI: "'PyInt_FromLong' was not declared in this scope", 55 times. pykcs11
— pulled in by endesive — ships no pre-generated wrapper, and its
`requires = ["swig"]` is unbounded: the LATEST published version runs, not
the system one. SWIG 4.3 dropped the Python 2 aliases it used to emit
itself, and pykcs11's CK_RV typemap uses one of them.
We hand the alias back to the preprocessor, token for token identical to
SWIG 4.2's. CPPFLAGS, not CFLAGS: a .cpp goes through compiler_so_cxx.
Verified on the VM and here: poetry install returns 0, import PyKCS11 works.
Assisted-by: Claude Opus 5
2026-08-22 05:07:06 -04:00
|
|
|
|
# pykcs11 — tiré par endesive, donc présent dans les locks 14, 15 et 17 —
|
|
|
|
|
|
# ne livre AUCUN wrapper pré-généré dans son sdist : SWIG tourne à CHAQUE
|
|
|
|
|
|
# installation. Et ce n'est pas le SWIG du système qui tourne : le
|
|
|
|
|
|
# « requires = ["setuptools", "swig"] » de pykcs11 n'est pas borné, donc
|
|
|
|
|
|
# Poetry télécharge la DERNIÈRE version publiée sur PyPI (4.5.0 le 21 août
|
|
|
|
|
|
# 2026, vue dans le journal d'installation).
|
|
|
|
|
|
#
|
|
|
|
|
|
# Or SWIG a retiré en 4.3 les alias Python 2 que ses versions antérieures
|
|
|
|
|
|
# écrivaient dans le code généré (PyInt_FromLong, PyString_Check…), et le
|
|
|
|
|
|
# typemap CK_RV de pykcs11 en utilise un. D'où, sur une VM Ubuntu 26.04:
|
|
|
|
|
|
# « ‘PyInt_FromLong’ was not declared in this scope », 55 fois, et
|
|
|
|
|
|
# install_odoo_17 s'arrête. Aucune sonde locale ne peut le prévoir — le
|
|
|
|
|
|
# SWIG qui tourne est choisi au moment du build, pas ici.
|
|
|
|
|
|
#
|
|
|
|
|
|
# On redonne l'alias au préprocesseur, dans la forme EXACTE que SWIG 4.2
|
|
|
|
|
|
# écrivait : définition identique token pour token, donc aucun
|
|
|
|
|
|
# avertissement de redéfinition là où SWIG la fournit encore (vérifié en
|
|
|
|
|
|
# -Werror contre un wrapper généré par SWIG 4.2).
|
|
|
|
|
|
#
|
|
|
|
|
|
# CPPFLAGS et non CFLAGS : un .cpp passe par « compiler_so_cxx », qui lit
|
|
|
|
|
|
# CXXFLAGS et CPPFLAGS — CFLAGS ne l'atteint JAMAIS. Mesuré sur setuptools
|
|
|
|
|
|
# 84, et c'est ce qui a fait échouer le premier correctif.
|
|
|
|
|
|
export CPPFLAGS="${CPPFLAGS:+${CPPFLAGS} }-DPyInt_FromLong(x)=PyLong_FromLong(x)"
|
[ADD] install: uv to place Python packages, pip as fallback
uv replaces pip where it can: the tools venv and the Poetry bootstrap. The
choice lives in EL_PIP_PROVIDER -- auto, uv or pip -- and in a single
file, lib_pip_provider.sh, on the exact model of the mise/pyenv switch. A
uv failure falls back to pip: it is stricter on metadata and rejects
packages pip accepts.
Three guards. The target always goes through "--python" rather than being
inferred from the active venv: poetry.toml declares a "./.venv" uv would
also look for. Python 3.7, still used by Odoo 12 and 13, stays on pip. And
"uv pip sync" is never used: it would delete pip itself and everything
Poetry laid down.
One bug falls along the way: the idempotence guard aimed at
.venv.erplibre/bin/poetry while Poetry installs into the Odoo venv, so a
successful replay reported failure all the same.
--- FR ---
uv remplace pip là où il le peut : le venv d'outils et l'amorçage de
Poetry. Le choix vit dans EL_PIP_PROVIDER — auto, uv ou pip — et dans un
seul fichier, lib_pip_provider.sh, sur le modèle exact de l'aiguillage
mise/pyenv. Un échec d'uv retombe sur pip : il est plus strict sur les
métadonnées et refuse des paquets que pip accepte.
Trois gardes. La cible passe toujours par « --python » plutôt que d'être
déduite du venv actif : poetry.toml déclare un « ./.venv » qu'uv
chercherait aussi. Python 3.7, encore utilisé par Odoo 12 et 13, reste sur
pip. Et « uv pip sync » n'est jamais employé : il supprimerait pip
lui-même et tout ce que Poetry a posé.
Un défaut tombe au passage : le garde d'idempotence visait
.venv.erplibre/bin/poetry alors que Poetry s'installe dans le venv Odoo,
si bien qu'un rejeu réussi rapportait quand même un échec.
Assisted-by: Claude Opus 5
2026-08-11 23:16:26 -04:00
|
|
|
|
# « poetry install » reste à Poetry : uv ne lit pas poetry.lock
|
|
|
|
|
|
# (astral-sh/uv#1804, « not planned ») et Poetry 2.1.3 n'a plus « export ».
|
|
|
|
|
|
if [[ ${WITH_POETRY_INSTALLATION} -ne 0 ]]; then
|
|
|
|
|
|
"${POETRY_ODOO_PATH}" install --no-root ${POETRY_VERBOSE}
|
2026-03-30 22:08:00 -04:00
|
|
|
|
retVal=$?
|
|
|
|
|
|
if [[ $retVal -ne 0 ]]; then
|
|
|
|
|
|
echo "Poetry installation error with status ${retVal}"
|
[ADD] install: uv to place Python packages, pip as fallback
uv replaces pip where it can: the tools venv and the Poetry bootstrap. The
choice lives in EL_PIP_PROVIDER -- auto, uv or pip -- and in a single
file, lib_pip_provider.sh, on the exact model of the mise/pyenv switch. A
uv failure falls back to pip: it is stricter on metadata and rejects
packages pip accepts.
Three guards. The target always goes through "--python" rather than being
inferred from the active venv: poetry.toml declares a "./.venv" uv would
also look for. Python 3.7, still used by Odoo 12 and 13, stays on pip. And
"uv pip sync" is never used: it would delete pip itself and everything
Poetry laid down.
One bug falls along the way: the idempotence guard aimed at
.venv.erplibre/bin/poetry while Poetry installs into the Odoo venv, so a
successful replay reported failure all the same.
--- FR ---
uv remplace pip là où il le peut : le venv d'outils et l'amorçage de
Poetry. Le choix vit dans EL_PIP_PROVIDER — auto, uv ou pip — et dans un
seul fichier, lib_pip_provider.sh, sur le modèle exact de l'aiguillage
mise/pyenv. Un échec d'uv retombe sur pip : il est plus strict sur les
métadonnées et refuse des paquets que pip accepte.
Trois gardes. La cible passe toujours par « --python » plutôt que d'être
déduite du venv actif : poetry.toml déclare un « ./.venv » qu'uv
chercherait aussi. Python 3.7, encore utilisé par Odoo 12 et 13, reste sur
pip. Et « uv pip sync » n'est jamais employé : il supprimerait pip
lui-même et tout ce que Poetry a posé.
Un défaut tombe au passage : le garde d'idempotence visait
.venv.erplibre/bin/poetry alors que Poetry s'installe dans le venv Odoo,
si bien qu'un rejeu réussi rapportait quand même un échec.
Assisted-by: Claude Opus 5
2026-08-11 23:16:26 -04:00
|
|
|
|
# Un rejeu, parce qu'une partie des échecs sont des aléas de
|
|
|
|
|
|
# téléchargement : le lock est figé, rien ne dépend de l'instant.
|
|
|
|
|
|
# « -vvv » est le SEUL niveau où Poetry montre la sortie des
|
|
|
|
|
|
# sous-processus (git clone, build pip), donc l'erreur réelle.
|
|
|
|
|
|
#
|
|
|
|
|
|
# Le « exit 1 » était INCONDITIONNEL : un rejeu réussi laissait une
|
|
|
|
|
|
# installation complète... et la déclarait quand même en échec.
|
|
|
|
|
|
# C'est ce qui a arrêté openSUSE Leap 16 sur un pdfminer-six posé
|
|
|
|
|
|
# correctement au second essai.
|
|
|
|
|
|
echo "---- Poetry: rejeu -vvv (diagnostic et seconde chance) ----"
|
|
|
|
|
|
if "${POETRY_ODOO_PATH}" install --no-root -vvv 2>&1; then
|
|
|
|
|
|
echo "Le rejeu a REUSSI : le premier echec etait transitoire."
|
|
|
|
|
|
else
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
2026-03-30 22:08:00 -04:00
|
|
|
|
fi
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
# Delete artifacts created by pip, cause error in next "poetry install"
|
|
|
|
|
|
rm -rf artifacts
|
2020-07-24 02:20:30 -04:00
|
|
|
|
|
2026-03-30 22:08:00 -04:00
|
|
|
|
# Link for dev tools into Odoo
|
|
|
|
|
|
echo -e "\n---- Add link dependency in site-packages of Python ----"
|
|
|
|
|
|
# TODO this link can break, the symbolic link is maybe not created
|
|
|
|
|
|
ln -fs "${EL_HOME_ODOO}/odoo" "${EL_HOME}/${VENV_ODOO_PATH}/lib/python${PYTHON_VERSION_MAJOR}/site-packages/"
|
2025-05-05 04:43:13 -04:00
|
|
|
|
|
2026-03-30 22:08:00 -04:00
|
|
|
|
# Force to return to erplibre source
|
|
|
|
|
|
source ./${VENV_ERPLIBRE_PATH}/bin/activate
|
2025-05-05 04:43:13 -04:00
|
|
|
|
|
2026-03-30 22:08:00 -04:00
|
|
|
|
# Add trace of installation
|
|
|
|
|
|
LINE_TO_ADD="odoo${EL_ODOO_VERSION}"
|
|
|
|
|
|
mkdir -p "$(dirname "$FILE_INSTALLATION_VERSION")"
|
|
|
|
|
|
touch "$FILE_INSTALLATION_VERSION"
|
|
|
|
|
|
if ! grep -qxF "$LINE_TO_ADD" "$FILE_INSTALLATION_VERSION"; then
|
|
|
|
|
|
echo "$LINE_TO_ADD" >> "$FILE_INSTALLATION_VERSION"
|
|
|
|
|
|
fi
|
2025-05-05 04:43:13 -04:00
|
|
|
|
fi
|