553 lines
16 KiB
Bash
553 lines
16 KiB
Bash
#!/bin/bash
|
|
|
|
# Copyright 2024 Fabrizio Forlini <fabrizio@forlini.it>
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
# Version: 1.0.0
|
|
|
|
set -uo pipefail
|
|
|
|
readonly orm_file="${HOME}/.oca-repos-manager/orm.conf"
|
|
|
|
readonly color_success="\e[32m"
|
|
readonly color_warning="\e[33m"
|
|
readonly color_danger="\e[31m"
|
|
readonly color_link="\e[36m"
|
|
readonly color_end="\e[0m"
|
|
readonly bold="\e[1m"
|
|
readonly bold_end="\e[0m"
|
|
|
|
update_all() {
|
|
local repos=( $(get_local_repos) )
|
|
|
|
update_oca_repos "${repos[@]}"
|
|
update_ocb
|
|
}
|
|
|
|
update_ocb() {
|
|
local exit_code
|
|
|
|
printf "\n%s\n" "Start updating OCB..."
|
|
|
|
echo "Entering: ${ocb_install_path}" >&2
|
|
cd ${ocb_install_path} && git pull
|
|
exit_code=$?
|
|
if [[ "${exit_code}" -ne 0 ]]; then
|
|
printf "${color_danger}%s${color_end},\n" "Error! Something was wrong updating OCB..."
|
|
fi
|
|
|
|
if [[ "${exit_code}" -eq 0 ]]; then
|
|
printf "\n${bold}%b${bold_end}\n" "Update complete!"
|
|
else
|
|
printf "${color_danger}%s${color_end}\n" "Error! Something was wrong during the update process."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
show_installed_repos_path() {
|
|
local content=( $( find ${oca_addons_install_path} -mindepth 1 -maxdepth 1 -type d ) )
|
|
if [[ -z ${content[@]} ]]; then
|
|
printf "\n\n\t\t${bold}%b${bold_end}\n" "No repositories found!"
|
|
else
|
|
printf "\n\n%s\n\n" "Please, ENSURE 'addons_path' variable in your Odoo configuration file contains:"
|
|
printf "${color_success}\t%b${color_end},\n" "${content[@]}"
|
|
fi
|
|
}
|
|
|
|
get_local_repos() {
|
|
local local_repos=( $( find ${oca_addons_install_path} -mindepth 1 -maxdepth 1 -type d -exec basename {} \; ) )
|
|
echo "${local_repos[@]}"
|
|
}
|
|
|
|
select_oca_repos_to_update() {
|
|
local repos=( $(get_local_repos) )
|
|
local selected_repos
|
|
|
|
select_repos "update_oca_repos" "${repos[@]}"
|
|
}
|
|
|
|
update_oca_repos() {
|
|
local exit_code
|
|
|
|
printf "\n%s\n" "Start updating..."
|
|
|
|
for repo in $@; do
|
|
echo "Entering: ${oca_addons_install_path}/${repo}" >&2
|
|
cd ${oca_addons_install_path}/${repo} && git pull
|
|
exit_code=$?
|
|
if [[ "${exit_code}" -ne 0 ]]; then
|
|
printf "${color_danger}%s${color_end},\n" "Error! Something was wrong updating ${repo} repository..."
|
|
fi
|
|
done
|
|
if [[ "${exit_code}" -eq 0 ]]; then
|
|
printf "\n${bold}%b${bold_end}\n" "Update complete!"
|
|
else
|
|
printf "${color_danger}%s${color_end}\n" "Error! Something was wrong during the update process."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
select_repos_to_clone() {
|
|
local repos
|
|
|
|
while true; do
|
|
if [ -z "${gh_token:-}" ]; then
|
|
set_github_token
|
|
fi
|
|
if [[ $(verify_github_token "${gh_token}") == false ]]; then
|
|
printf "\n${color_danger}%b${color_end}" "Token not valid!"
|
|
set_github_token
|
|
continue
|
|
fi
|
|
break
|
|
done
|
|
|
|
repos=( $(get_repos_names) )
|
|
|
|
select_repos "clone_repos" "${repos[@]}"
|
|
show_installed_repos_path
|
|
}
|
|
|
|
clone_repos() {
|
|
local exit_code
|
|
|
|
printf "\n%s\n" "Start cloning..."
|
|
|
|
for repo in ${@}; do
|
|
if [[ -d "${oca_addons_install_path}/${repo}" ]]; then
|
|
printf "${color_warning}%b${color_end},\n" "Repo ${repo} already exist! Skipped..."
|
|
continue
|
|
fi
|
|
cd ${oca_addons_install_path} && git clone https://github.com/OCA/${repo}.git --branch ${odoo_version} --single-branch
|
|
if [[ "${?}" -ne 0 ]]; then
|
|
printf "${color_danger}%s${color_end},\n" "Error! Something was wrong cloning ${repo} repository..."
|
|
fi
|
|
done
|
|
|
|
printf "\n${bold}%b${bold_end}\n" "Clone complete!"
|
|
}
|
|
|
|
select_repos() {
|
|
local cmd=$1
|
|
shift
|
|
local repos_names=("${@}")
|
|
local selected=()
|
|
local item
|
|
local nums=()
|
|
local num
|
|
|
|
COLUMNS=$(tput cols)
|
|
|
|
if [[ ! -z "${repos_names[@]}" ]]; then
|
|
while true; do
|
|
selected=()
|
|
nums=()
|
|
|
|
echo -e "\n"
|
|
|
|
PS3=$'\nPlease, select the repositories : (eg: "1 2 3", "1-3", repo name, or "A" for ALL)\n==> '
|
|
select _ in "${repos_names[@]}" ; do
|
|
for item in ${REPLY}; do
|
|
if [[ "${item}" =~ ^(A)+$ ]]; then
|
|
selected+=( "${repos_names[@]}" )
|
|
break
|
|
fi
|
|
if [[ "${item}" =~ ^([0-9]*)-([0-9]*)+$ ]]; then
|
|
nums+=( $( seq ${item//[!0-9]/ } ) )
|
|
fi
|
|
if [[ "${item}" =~ ^[0-9]+$ ]]; then
|
|
nums+=( ${item} )
|
|
fi
|
|
if [[ " ${repos_names[*]} " = *" ${item} "* ]]; then
|
|
selected+=( ${item} )
|
|
fi
|
|
done
|
|
for num in "${nums[@]}"; do
|
|
if [[ -n "${num}" && "${num}" -gt 0 && "${num}" -le "${#repos_names[@]}" ]]; then
|
|
selected+=(${repos_names[num - 1]})
|
|
fi
|
|
done
|
|
[[ ${#selected[@]} -gt 0 ]] && break
|
|
done
|
|
|
|
echo -e "\n"
|
|
echo "--------------------------------------------------------"
|
|
echo " SELECTED REPOS "
|
|
echo "--------------------------------------------------------"
|
|
printf "%b\n" "${selected[@]}"
|
|
echo "--------------------------------------------------------"
|
|
echo
|
|
echo "Do you want to proceed? [y/N]"
|
|
echo -n "==> "
|
|
read -sn 1
|
|
|
|
case "${REPLY}" in
|
|
Y|y)
|
|
${cmd} "${selected[@]}"
|
|
break
|
|
;;
|
|
*)
|
|
continue
|
|
;;
|
|
esac
|
|
done
|
|
else
|
|
printf "\n\n\t\t${bold}%b${bold_end}\n" "No repositories found!"
|
|
fi
|
|
}
|
|
|
|
sort_array() {
|
|
sorted=()
|
|
while IFS= read -rd '' item; do
|
|
sorted+=("$item")
|
|
done < <(printf '%s\0' "$@" | sort -z)
|
|
|
|
echo "${sorted[@]}"
|
|
}
|
|
|
|
get_repos_names() {
|
|
local repos_names
|
|
local repo_name
|
|
local branch_content
|
|
local content_is_present
|
|
local all_repos_names=( $(get_all_repos_names) )
|
|
|
|
echo -en "\nFetching OCA repositories for version ${odoo_version}..." >&2
|
|
|
|
for repo_name in "${all_repos_names[@]}"; do
|
|
echo -n "." >&2
|
|
branch_content=$(curl -s -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${gh_token}" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/OCA/"${repo_name}"/contents\?ref\="${odoo_version}")
|
|
|
|
content_is_present=$(echo "${branch_content}" | jq -e 'any(arrays[]; .name | . == "README.md" or . == "LICENSE" or . == "setup" or startswith(".") | not)')
|
|
|
|
if [[ "${content_is_present}" == true ]]; then
|
|
repos_names+=("${repo_name}")
|
|
fi
|
|
done
|
|
|
|
echo >&2
|
|
echo "Found ${#all_repos_names[@]} OCA repositories!" >&2
|
|
echo "Found ${#repos_names[@]} OCA repositories for Odoo ${odoo_version}!" >&2
|
|
|
|
repos_names=( $(sort_array "${repos_names[@]}") )
|
|
|
|
echo "${repos_names[@]}"
|
|
}
|
|
|
|
get_all_repos_names() {
|
|
local page
|
|
local repos_in_the_page
|
|
local repos_names_in_the_page
|
|
local all_repos_names
|
|
local ignore_repos_list=(".github" "OCB")
|
|
|
|
printf "\n\n%b" "Fetching OCA repositories..." >&2
|
|
|
|
page=1
|
|
|
|
while true; do
|
|
echo -n "." >&2
|
|
repos_in_the_page=$(curl -s -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${gh_token}" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/orgs/OCA/repos?per_page=100\&page=${page}\&sort=updated)
|
|
repos_names_in_the_page=(
|
|
$( echo "${repos_in_the_page}" | jq -r '.[].name' | while read -r name; do
|
|
for ignored_repo in "${ignore_repos_list[@]}"; do
|
|
if [[ "${name}" == "${ignored_repo}" ]]; then
|
|
continue 2
|
|
fi
|
|
done
|
|
echo "${name}";
|
|
done
|
|
)
|
|
)
|
|
|
|
if [[ "${#repos_names_in_the_page[@]}" == 0 ]]; then
|
|
break
|
|
fi
|
|
|
|
((page++))
|
|
|
|
all_repos_names+=( "${repos_names_in_the_page[@]}" )
|
|
done
|
|
|
|
echo "${all_repos_names[@]}"
|
|
}
|
|
|
|
verify_github_token() {
|
|
local token=$1
|
|
local status_code=$(curl --write-out '%{http_code}' --silent --output /dev/null -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${gh_token}" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/user)
|
|
|
|
if [[ "${status_code}" -ne 200 ]]; then
|
|
echo false
|
|
else
|
|
echo true
|
|
fi
|
|
}
|
|
|
|
set_github_token() {
|
|
local token
|
|
|
|
printf "\n\n${bold}%b${bold_end} %b\n" "Github Personal Access Token is required." "Don't you have one?"
|
|
printf "%b ${bold}${color_link}%b${color_end}${bold_end}\n\n" "Go here and create it:" "https://github.com/settings/tokens"
|
|
echo "Please. enter your Github Personal Access Token:"
|
|
echo -n "==> "
|
|
read -e token
|
|
|
|
save_in_config_file "gh_token" "${token}"
|
|
}
|
|
|
|
set_oca_addons_install_path() {
|
|
local path_selected
|
|
|
|
while true; do
|
|
printf "\n\n%s\n" "Please, insert the OCA addons install path."
|
|
echo "[Enter for default: /opt/odoo/${odoo_version}/addons/OCA/ ]:"
|
|
echo -n "==> "
|
|
read -e path_selected
|
|
|
|
if [[ -z "${path_selected:-}" ]]; then
|
|
path_selected="/opt/odoo/${odoo_version}/addons/OCA/"
|
|
fi
|
|
|
|
if [[ ! -d "${path_selected}" ]]; then
|
|
printf "\n\n${color_danger}%s${color_end}" "Path doesn't exist! Please, insert an existing one."
|
|
continue
|
|
fi
|
|
|
|
break
|
|
done
|
|
|
|
# Remove trailing slash if present
|
|
path_selected="${path_selected%/}"
|
|
|
|
save_in_config_file "oca_addons_install_path" "${path_selected}"
|
|
}
|
|
|
|
set_ocb_install_path() {
|
|
local path_selected
|
|
|
|
while true; do
|
|
printf "\n\n%s\n" "Please, insert the OCB install path."
|
|
echo "[Enter for default: /opt/odoo/${odoo_version}/OCB/ ]:"
|
|
echo -n "==> "
|
|
read -e path_selected
|
|
|
|
if [[ -z "${path_selected:-}" ]]; then
|
|
path_selected="/opt/odoo/${odoo_version}/OCB/"
|
|
fi
|
|
|
|
if [[ ! -d "${path_selected}" ]]; then
|
|
printf "\n\n${color_danger}%s${color_end}" "Path doesn't exist! Please, insert an existing one."
|
|
continue
|
|
fi
|
|
|
|
break
|
|
done
|
|
|
|
# Remove trailing slash if present
|
|
path_selected="${path_selected%/}"
|
|
|
|
save_in_config_file "ocb_install_path" "${path_selected}"
|
|
}
|
|
|
|
set_odoo_version() {
|
|
local odoo_version_selected
|
|
|
|
while true; do
|
|
printf "\n\n%b\n" "Please, select the Odoo version of your interest."
|
|
echo "[E.g. 14 -> for Odoo v14.0, 16 -> for Odoo v16.0, etc.]:"
|
|
echo -n "==> "
|
|
read -e odoo_version_selected
|
|
[[ "${odoo_version_selected}" =~ ^[[:digit:]]+$ ]] || continue
|
|
(( ( "${odoo_version_selected}" >= 1 ) && ( "${odoo_version_selected}" <= 30 ) )) || continue
|
|
odoo_version_selected="${odoo_version_selected}.0"
|
|
|
|
save_in_config_file "odoo_version" "${odoo_version_selected}"
|
|
break
|
|
done
|
|
}
|
|
|
|
save_in_config_file() {
|
|
local key=$1
|
|
local value=$2
|
|
|
|
if ! grep -q "${key}=" "${orm_file}"; then
|
|
echo "${key}=${value}" >> ${orm_file};
|
|
get_config_file
|
|
return
|
|
fi
|
|
sed -i.bak "s:${key}.*:${key}=${value}:g" "${orm_file}"
|
|
get_config_file
|
|
}
|
|
|
|
get_config_file() {
|
|
mkdir -p $(dirname "${orm_file}")
|
|
touch "${orm_file}"
|
|
|
|
source "${orm_file}" 2>/dev/null
|
|
}
|
|
|
|
settings_menu() {
|
|
while true; do
|
|
echo
|
|
echo "********************************************************"
|
|
echo " SETTINGS "
|
|
echo "********************************************************"
|
|
printf "${bold}%s ${color_success}%b${color_end}\n" " > Odoo target version:" "${odoo_version}"
|
|
printf "${bold}%s ${color_success}%b${color_end}\n" " > OCB install path:" "${ocb_install_path}"
|
|
printf "${bold}%s ${color_success}%b${color_end}\n" " > OCA addons install path:" "${oca_addons_install_path}"
|
|
echo "********************************************************"
|
|
echo
|
|
echo "1) Change Odoo target version"
|
|
echo "2) Change OCB install path"
|
|
echo "3) Change OCA addons install path"
|
|
echo "---"
|
|
echo "4) Back"
|
|
echo
|
|
echo -n "==> "
|
|
read -sn 1
|
|
|
|
case "${REPLY}" in
|
|
1)
|
|
set_odoo_version
|
|
continue
|
|
;;
|
|
2)
|
|
set_ocb_install_path
|
|
continue
|
|
;;
|
|
3)
|
|
set_oca_addons_install_path
|
|
continue
|
|
;;
|
|
4)
|
|
main_menu
|
|
break
|
|
;;
|
|
*)
|
|
echo "Choice not valid!"
|
|
continue
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
main_menu() {
|
|
while true; do
|
|
echo
|
|
echo "********************************************************"
|
|
printf "\t\t\t${bold}%s${bold_end}\n" "MAIN MENU"
|
|
echo "********************************************************"
|
|
echo
|
|
echo "1) Clone OCA repositories"
|
|
echo "2) Show installed repositories path for Odoo config file"
|
|
echo "3) Update OCA repositories already cloned"
|
|
echo "4) Update OCB"
|
|
echo "5) Update All"
|
|
echo "---"
|
|
echo "6) Settings"
|
|
echo "---"
|
|
echo "q) Exit"
|
|
echo
|
|
echo -n "==> "
|
|
read -sn 1
|
|
|
|
case "${REPLY}" in
|
|
1)
|
|
select_repos_to_clone
|
|
read -p $'\nPress any key to continue...'
|
|
continue
|
|
;;
|
|
2)
|
|
show_installed_repos_path
|
|
read -p $'\nPress any key to continue...'
|
|
continue
|
|
;;
|
|
3)
|
|
select_oca_repos_to_update
|
|
read -p $'\nPress any key to continue...'
|
|
continue
|
|
;;
|
|
4)
|
|
update_ocb
|
|
read -p $'\nPress any key to continue...'
|
|
continue
|
|
;;
|
|
5)
|
|
update_all
|
|
read -p $'\nPress any key to continue...'
|
|
continue
|
|
;;
|
|
6)
|
|
settings_menu
|
|
continue
|
|
;;
|
|
q|Q)
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Choice not valid!"
|
|
continue
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
check_dependencies() {
|
|
for cmd in "${@}"; do
|
|
command -v "${cmd}" > /dev/null
|
|
local exitcode=$?
|
|
if [[ "${exitcode}" -ne "0" ]]; then
|
|
echo -e "\n${cmd} is missing. Please, install it. E.g.: apt install ${cmd}"
|
|
echo -e "\nQuitting..."
|
|
exit "${exitcode}"
|
|
fi
|
|
done
|
|
}
|
|
|
|
intro_banner() {
|
|
echo
|
|
echo
|
|
echo " ╔═╗╔═╗╔═╗ "
|
|
echo " ║ ║║ ╠═╣ "
|
|
echo " ╚═╝╚═╝╩ ╩ "
|
|
echo " ┬─┐┌─┐┌─┐┌─┐┌─┐ ┌┬┐┌─┐┌┐┌┌─┐┌─┐┌─┐┬─┐ "
|
|
echo " ├┬┘├┤ ├─┘│ │└─┐ │││├─┤│││├─┤│ ┬├┤ ├┬┘ "
|
|
echo " ┴└─└─┘┴ └─┘└─┘ ┴ ┴┴ ┴┘└┘┴ ┴└─┘└─┘┴└─ "
|
|
echo
|
|
}
|
|
|
|
main() {
|
|
intro_banner
|
|
check_dependencies jq curl git
|
|
|
|
get_config_file
|
|
|
|
if [[ -z "${odoo_version+x:-}" ]]; then
|
|
set_odoo_version
|
|
fi
|
|
|
|
if [[ -z "${ocb_install_path+x:-}" ]]; then
|
|
set_ocb_install_path
|
|
fi
|
|
|
|
if [[ -z "${oca_addons_install_path+x:-}" ]]; then
|
|
set_oca_addons_install_path
|
|
fi
|
|
|
|
main_menu
|
|
}
|
|
|
|
main
|