2024-08-26 14:55:36 -04:00
|
|
|
#!/usr/bin/env python3
|
2026-03-11 23:15:07 -04:00
|
|
|
# © 2021-2026 TechnoLibre (http://www.technolibre.ca)
|
2024-08-26 14:55:36 -04:00
|
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
|
|
|
|
|
2022-01-24 14:00:47 -05:00
|
|
|
import argparse
|
|
|
|
|
import configparser
|
2025-10-31 01:10:54 -04:00
|
|
|
import json
|
2022-01-24 14:00:47 -05:00
|
|
|
import logging
|
|
|
|
|
import os
|
|
|
|
|
import sys
|
|
|
|
|
from collections import defaultdict
|
|
|
|
|
|
|
|
|
|
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__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_config():
|
|
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
|
|
|
description="""\
|
|
|
|
|
Check if module exist and is not multiple here to manage conflict.
|
2024-03-17 14:00:27 -04:00
|
|
|
Return 0 if success, return 1 if missing module, return 2 if multiple same module
|
2022-01-24 14:00:47 -05:00
|
|
|
""",
|
|
|
|
|
epilog="""\
|
|
|
|
|
""",
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"-m",
|
|
|
|
|
"--module",
|
|
|
|
|
required=True,
|
|
|
|
|
help="Module name to search, a list can be use separate by ,",
|
|
|
|
|
)
|
2022-02-10 00:40:56 -05:00
|
|
|
parser.add_argument(
|
|
|
|
|
"-c",
|
|
|
|
|
"--config",
|
|
|
|
|
default="./config.conf",
|
|
|
|
|
help="The config path.",
|
|
|
|
|
)
|
2022-01-24 14:00:47 -05:00
|
|
|
parser.add_argument(
|
|
|
|
|
"--debug",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Enable debug output",
|
|
|
|
|
)
|
2024-01-05 01:52:52 -05:00
|
|
|
parser.add_argument(
|
|
|
|
|
"--output_path",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Print path if module exist",
|
|
|
|
|
)
|
2025-10-31 01:10:54 -04:00
|
|
|
parser.add_argument(
|
|
|
|
|
"--output_json",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="output json for automation",
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--format_json",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="output formated json",
|
|
|
|
|
)
|
2022-01-24 14:00:47 -05:00
|
|
|
args = parser.parse_args()
|
|
|
|
|
return args
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
config = get_config()
|
|
|
|
|
if config.debug:
|
|
|
|
|
logging.getLogger().setLevel(logging.DEBUG)
|
2025-10-31 01:10:54 -04:00
|
|
|
if not config.output_path and config.output_json:
|
|
|
|
|
config.output_path = True
|
2022-01-24 14:00:47 -05:00
|
|
|
|
|
|
|
|
config_parser = configparser.ConfigParser()
|
2022-02-10 00:40:56 -05:00
|
|
|
config_parser.read(config.config)
|
2022-01-24 14:00:47 -05:00
|
|
|
if "options" in config_parser:
|
|
|
|
|
if "addons_path" in config_parser["options"]:
|
|
|
|
|
addons_path = config_parser["options"]["addons_path"]
|
|
|
|
|
else:
|
2025-10-31 01:10:54 -04:00
|
|
|
msg = f"Missing item 'addons_path' in section 'options' in '{config.config}'"
|
|
|
|
|
if not config.output_json:
|
|
|
|
|
_logger.error(msg)
|
|
|
|
|
else:
|
|
|
|
|
print("{'error':%s}" % msg)
|
2022-01-24 14:00:47 -05:00
|
|
|
return -1
|
|
|
|
|
else:
|
2025-10-31 01:10:54 -04:00
|
|
|
msg = f"Missing section 'options' in '{config.config}'"
|
|
|
|
|
if not config.output_json:
|
|
|
|
|
_logger.error(msg)
|
|
|
|
|
else:
|
|
|
|
|
print("{'error':%s}" % msg)
|
2022-01-24 14:00:47 -05:00
|
|
|
return -1
|
|
|
|
|
|
2023-01-06 16:55:27 -05:00
|
|
|
lst_addons_path = addons_path.strip(",").split(",")
|
2025-10-31 01:10:54 -04:00
|
|
|
lst_module = sorted(list(set(config.module.strip(",").split(","))))
|
2022-01-24 14:00:47 -05:00
|
|
|
|
|
|
|
|
dct_module_exist = defaultdict(list)
|
|
|
|
|
dct_module_exist_empty = defaultdict(list)
|
|
|
|
|
lst_module_not_exist = []
|
2025-10-31 01:10:54 -04:00
|
|
|
lst_error = []
|
|
|
|
|
lst_exist = []
|
|
|
|
|
lst_missing = []
|
|
|
|
|
lst_duplicate = []
|
2022-01-24 14:00:47 -05:00
|
|
|
|
|
|
|
|
for module in lst_module:
|
|
|
|
|
for path in lst_addons_path:
|
|
|
|
|
module_path = os.path.join(path, module)
|
|
|
|
|
manifest_file_path = os.path.join(module_path, "__manifest__.py")
|
|
|
|
|
if os.path.isdir(module_path):
|
|
|
|
|
if os.path.isfile(manifest_file_path):
|
|
|
|
|
dct_module_exist[module].append(module_path)
|
|
|
|
|
else:
|
|
|
|
|
dct_module_exist_empty[module].append(module_path)
|
|
|
|
|
|
|
|
|
|
if module not in dct_module_exist.keys():
|
|
|
|
|
lst_module_not_exist.append(module)
|
|
|
|
|
|
|
|
|
|
is_good = True
|
2024-03-17 14:00:27 -04:00
|
|
|
error_missing_module = False
|
2022-01-24 14:00:47 -05:00
|
|
|
if lst_module_not_exist:
|
|
|
|
|
is_good = False
|
2024-03-17 14:00:27 -04:00
|
|
|
error_missing_module = True
|
2022-01-24 14:00:47 -05:00
|
|
|
module_list = "'" + "', '".join(lst_module_not_exist) + "'"
|
2025-10-31 01:10:54 -04:00
|
|
|
msg = f"Missing module{'s' if len(lst_module_not_exist) > 1 else ''} {module_list}"
|
|
|
|
|
if not config.output_json:
|
|
|
|
|
_logger.error(msg)
|
|
|
|
|
else:
|
|
|
|
|
lst_missing.extend(lst_module_not_exist)
|
2022-01-24 14:00:47 -05:00
|
|
|
if dct_module_exist:
|
|
|
|
|
for key, lst_value in dct_module_exist.items():
|
2024-01-05 01:52:52 -05:00
|
|
|
is_print_value = False
|
2022-01-24 14:00:47 -05:00
|
|
|
if len(lst_value) != 1:
|
2024-01-05 01:52:52 -05:00
|
|
|
is_print_value = True
|
2022-01-24 14:00:47 -05:00
|
|
|
is_good = False
|
|
|
|
|
module_list = "'" + "', '".join(lst_value) + "'"
|
2025-10-31 01:10:54 -04:00
|
|
|
msg = f"Conflict modules: {module_list}"
|
|
|
|
|
if not config.output_json:
|
|
|
|
|
_logger.error(msg)
|
|
|
|
|
else:
|
|
|
|
|
lst_duplicate.append((key, lst_value))
|
2024-01-05 01:52:52 -05:00
|
|
|
elif lst_value and config.output_path:
|
|
|
|
|
is_print_value = True
|
|
|
|
|
if is_print_value:
|
2022-01-24 14:00:47 -05:00
|
|
|
for value in lst_value:
|
2025-10-31 01:10:54 -04:00
|
|
|
if len(lst_value) == 1:
|
|
|
|
|
lst_exist.append((key, value))
|
|
|
|
|
if not config.output_json:
|
|
|
|
|
print(value)
|
2022-01-24 14:00:47 -05:00
|
|
|
|
2024-03-17 14:00:27 -04:00
|
|
|
if dct_module_exist_empty and not config.output_path:
|
2022-01-24 14:00:47 -05:00
|
|
|
for key, lst_value in dct_module_exist_empty.items():
|
|
|
|
|
module_list = "'" + "', '".join(lst_value) + "'"
|
2025-10-31 01:10:54 -04:00
|
|
|
msg = f"Found this directory, but missing __manifest__.py: {module_list}"
|
|
|
|
|
if not config.output_json:
|
|
|
|
|
_logger.warning(msg)
|
|
|
|
|
else:
|
|
|
|
|
lst_error.append(msg)
|
|
|
|
|
|
|
|
|
|
if config.output_json:
|
|
|
|
|
dct_json_data = {
|
|
|
|
|
"exist": lst_exist,
|
|
|
|
|
"error": lst_error,
|
|
|
|
|
"duplicate": lst_duplicate,
|
|
|
|
|
"missing": lst_missing,
|
|
|
|
|
}
|
|
|
|
|
if config.format_json:
|
|
|
|
|
json_data = json.dumps(dct_json_data, indent=4, sort_keys=True)
|
|
|
|
|
else:
|
|
|
|
|
json_data = json.dumps(dct_json_data)
|
|
|
|
|
print(json_data)
|
2022-01-24 14:00:47 -05:00
|
|
|
|
2024-03-17 14:00:27 -04:00
|
|
|
if not is_good:
|
|
|
|
|
if error_missing_module:
|
|
|
|
|
return 1
|
|
|
|
|
return 2
|
|
|
|
|
return 0
|
2022-01-24 14:00:47 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
sys.exit(main())
|