140681896Sopenharmony_ci#!/usr/bin/env python3
240681896Sopenharmony_ci# -*- coding: utf-8 -*-
340681896Sopenharmony_ci
440681896Sopenharmony_ci# Copyright (c) 2023 Huawei Device Co., Ltd.
540681896Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
640681896Sopenharmony_ci# you may not use this file except in compliance with the License.
740681896Sopenharmony_ci# You may obtain a copy of the License at
840681896Sopenharmony_ci#
940681896Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0
1040681896Sopenharmony_ci#
1140681896Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software
1240681896Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
1340681896Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1440681896Sopenharmony_ci# See the License for the specific language governing permissions and
1540681896Sopenharmony_ci# limitations under the License.
1640681896Sopenharmony_ci
1740681896Sopenharmony_ci"""
1840681896Sopenharmony_ciThe tool for making hmp.
1940681896Sopenharmony_ci
2040681896Sopenharmony_cipositional arguments:
2140681896Sopenharmony_ci  -pn PACKAGE_NAME, --package_name PACKAGE_NAME
2240681896Sopenharmony_ci                        Module package name.
2340681896Sopenharmony_ci  -op OUT_PACKAGE, --out_package OUT_PACKAGE
2440681896Sopenharmony_ci                        Out package file path.
2540681896Sopenharmony_ci  -pi PACK_INFO, --pack_info PACK_INFO
2640681896Sopenharmony_ci                        Pack info file path.
2740681896Sopenharmony_ci  -mf MODULE_FILES, --module_files MODULE_FILES
2840681896Sopenharmony_ci                        Module files path.
2940681896Sopenharmony_ci"""
3040681896Sopenharmony_ciimport os
3140681896Sopenharmony_ciimport sys
3240681896Sopenharmony_ciimport argparse
3340681896Sopenharmony_ciimport zipfile
3440681896Sopenharmony_ciimport io
3540681896Sopenharmony_ciimport logging
3640681896Sopenharmony_ci
3740681896Sopenharmony_ci
3840681896Sopenharmony_ci# 1000000: max number of function recursion depth
3940681896Sopenharmony_ciMAXIMUM_RECURSION_DEPTH = 1000000
4040681896Sopenharmony_cisys.setrecursionlimit(MAXIMUM_RECURSION_DEPTH)
4140681896Sopenharmony_ci
4240681896Sopenharmony_ci
4340681896Sopenharmony_cidef package_name_check(arg):
4440681896Sopenharmony_ci    """
4540681896Sopenharmony_ci    Argument check, which is used to check whether the specified arg is none.
4640681896Sopenharmony_ci    :param arg: the arg to check
4740681896Sopenharmony_ci    :return:  Check result, which is False if the arg is invalid.
4840681896Sopenharmony_ci    """
4940681896Sopenharmony_ci    if arg is None:
5040681896Sopenharmony_ci        UPDATE_LOGGER.print_log(
5140681896Sopenharmony_ci            "Package name error: %s" % arg, UPDATE_LOGGER.ERROR_LOG)
5240681896Sopenharmony_ci        return False
5340681896Sopenharmony_ci    return arg
5440681896Sopenharmony_ci
5540681896Sopenharmony_ci
5640681896Sopenharmony_cidef check_out_package(arg):
5740681896Sopenharmony_ci    """
5840681896Sopenharmony_ci    Argument check, which is used to check whether
5940681896Sopenharmony_ci    the update package path exists.
6040681896Sopenharmony_ci    :param arg: The arg to check.
6140681896Sopenharmony_ci    :return: Check result
6240681896Sopenharmony_ci    """
6340681896Sopenharmony_ci    make_dir_path = None
6440681896Sopenharmony_ci    if os.path.exists(arg):
6540681896Sopenharmony_ci        if os.path.isfile(arg):
6640681896Sopenharmony_ci            UPDATE_LOGGER.print_log(
6740681896Sopenharmony_ci                "Out package must be a dir path, not a file path. "
6840681896Sopenharmony_ci                "path: %s" % arg, UPDATE_LOGGER.ERROR_LOG)
6940681896Sopenharmony_ci            return False
7040681896Sopenharmony_ci    else:
7140681896Sopenharmony_ci        try:
7240681896Sopenharmony_ci            UPDATE_LOGGER.print_log(
7340681896Sopenharmony_ci                "Out package path does not exist. The dir will be created!"
7440681896Sopenharmony_ci                "path: %s" % arg, UPDATE_LOGGER.WARNING_LOG)
7540681896Sopenharmony_ci            os.makedirs(arg)
7640681896Sopenharmony_ci            make_dir_path = arg
7740681896Sopenharmony_ci        except OSError:
7840681896Sopenharmony_ci            UPDATE_LOGGER.print_log(
7940681896Sopenharmony_ci                "Make out package path dir failed! "
8040681896Sopenharmony_ci                "path: %s" % arg, UPDATE_LOGGER.ERROR_LOG)
8140681896Sopenharmony_ci            return False
8240681896Sopenharmony_ci    return arg
8340681896Sopenharmony_ci
8440681896Sopenharmony_ci
8540681896Sopenharmony_cidef pack_info_check(arg):
8640681896Sopenharmony_ci    """
8740681896Sopenharmony_ci    Argument check, which is used to check whether
8840681896Sopenharmony_ci    the specified arg is a pack info.
8940681896Sopenharmony_ci    :param arg: the arg to check
9040681896Sopenharmony_ci    :return: Check result, which is False if the arg is invalid.
9140681896Sopenharmony_ci    """
9240681896Sopenharmony_ci    if not os.path.isfile(arg):
9340681896Sopenharmony_ci        UPDATE_LOGGER.print_log(
9440681896Sopenharmony_ci            "FileNotFoundError, path: %s" % arg, UPDATE_LOGGER.ERROR_LOG)
9540681896Sopenharmony_ci        return False
9640681896Sopenharmony_ci    return arg
9740681896Sopenharmony_ci
9840681896Sopenharmony_ci
9940681896Sopenharmony_ciclass UpdateToolLogger:
10040681896Sopenharmony_ci    """
10140681896Sopenharmony_ci    Global log class
10240681896Sopenharmony_ci    """
10340681896Sopenharmony_ci    INFO_LOG = 'INFO_LOG'
10440681896Sopenharmony_ci    WARNING_LOG = 'WARNING_LOG'
10540681896Sopenharmony_ci    ERROR_LOG = 'ERROR_LOG'
10640681896Sopenharmony_ci    LOG_TYPE = (INFO_LOG, WARNING_LOG, ERROR_LOG)
10740681896Sopenharmony_ci
10840681896Sopenharmony_ci    def __init__(self, output_type='console'):
10940681896Sopenharmony_ci        self.__logger_obj = self.__get_logger_obj(output_type=output_type)
11040681896Sopenharmony_ci
11140681896Sopenharmony_ci    @staticmethod
11240681896Sopenharmony_ci    def __get_logger_obj(output_type='console'):
11340681896Sopenharmony_ci        ota_logger = logging.getLogger(__name__)
11440681896Sopenharmony_ci        ota_logger.setLevel(level=logging.INFO)
11540681896Sopenharmony_ci        formatter = logging.Formatter(
11640681896Sopenharmony_ci            '%(asctime)s %(levelname)s : %(message)s',
11740681896Sopenharmony_ci            "%Y-%m-%d %H:%M:%S")
11840681896Sopenharmony_ci        if output_type == 'console':
11940681896Sopenharmony_ci            console_handler = logging.StreamHandler()
12040681896Sopenharmony_ci            console_handler.setLevel(logging.INFO)
12140681896Sopenharmony_ci            console_handler.setFormatter(formatter)
12240681896Sopenharmony_ci            ota_logger.addHandler(console_handler)
12340681896Sopenharmony_ci        elif output_type == 'file':
12440681896Sopenharmony_ci            file_handler = logging.FileHandler("UpdateToolLog.txt")
12540681896Sopenharmony_ci            file_handler.setLevel(logging.INFO)
12640681896Sopenharmony_ci            file_handler.setFormatter(formatter)
12740681896Sopenharmony_ci            ota_logger.addHandler(file_handler)
12840681896Sopenharmony_ci        return ota_logger
12940681896Sopenharmony_ci
13040681896Sopenharmony_ci    def print_log(self, msg, log_type=INFO_LOG):
13140681896Sopenharmony_ci        """
13240681896Sopenharmony_ci        Print log information.
13340681896Sopenharmony_ci        :param msg: log information
13440681896Sopenharmony_ci        :param log_type: log type
13540681896Sopenharmony_ci        :return:
13640681896Sopenharmony_ci        """
13740681896Sopenharmony_ci        if log_type == self.LOG_TYPE[0]:
13840681896Sopenharmony_ci            self.__logger_obj.info(msg)
13940681896Sopenharmony_ci        elif log_type == self.LOG_TYPE[1]:
14040681896Sopenharmony_ci            self.__logger_obj.warning(msg)
14140681896Sopenharmony_ci        elif log_type == self.LOG_TYPE[2]:
14240681896Sopenharmony_ci            self.__logger_obj.error(msg)
14340681896Sopenharmony_ci        else:
14440681896Sopenharmony_ci            self.__logger_obj.error("Unknown log type! %s", log_type)
14540681896Sopenharmony_ci            return False
14640681896Sopenharmony_ci        return True
14740681896Sopenharmony_ci
14840681896Sopenharmony_ci    def print_uncaught_exception_msg(self, msg, exc_info):
14940681896Sopenharmony_ci        """
15040681896Sopenharmony_ci        Print log when an uncaught exception occurs.
15140681896Sopenharmony_ci        :param msg: Uncaught exception
15240681896Sopenharmony_ci        :param exc_info: information about the uncaught exception
15340681896Sopenharmony_ci        """
15440681896Sopenharmony_ci        self.__logger_obj.error(msg, exc_info=exc_info)
15540681896Sopenharmony_ci
15640681896Sopenharmony_ci
15740681896Sopenharmony_ciUPDATE_LOGGER = UpdateToolLogger()
15840681896Sopenharmony_ci
15940681896Sopenharmony_ci
16040681896Sopenharmony_cidef build_hmp(package_name, out_package, pack_info, module_files):
16140681896Sopenharmony_ci    out_package_path = os.path.join(
16240681896Sopenharmony_ci        out_package, '%s.zip' % package_name)
16340681896Sopenharmony_ci    zip_file = zipfile.ZipFile(out_package_path, 'w', zipfile.ZIP_DEFLATED, allowZip64=True)
16440681896Sopenharmony_ci    for module_file in module_files:
16540681896Sopenharmony_ci        zip_file.write(module_file, os.path.basename(module_file))
16640681896Sopenharmony_ci    zip_file.write(pack_info, os.path.basename(pack_info))
16740681896Sopenharmony_ci    zip_file.close()
16840681896Sopenharmony_ci    return True
16940681896Sopenharmony_ci
17040681896Sopenharmony_ci
17140681896Sopenharmony_cidef main(argv):
17240681896Sopenharmony_ci    """
17340681896Sopenharmony_ci    Entry function.
17440681896Sopenharmony_ci    """
17540681896Sopenharmony_ci    parser = argparse.ArgumentParser()
17640681896Sopenharmony_ci
17740681896Sopenharmony_ci    parser.add_argument("-pn", "--package_name", type=package_name_check,
17840681896Sopenharmony_ci                        default=None, help="Module package name.")
17940681896Sopenharmony_ci    parser.add_argument("-op", "--out_package", type=check_out_package,
18040681896Sopenharmony_ci                        default=None, help="Out package file path.")
18140681896Sopenharmony_ci    parser.add_argument("-pi", "--pack_info", type=pack_info_check,
18240681896Sopenharmony_ci                        default=None, help="Pack info file path.")
18340681896Sopenharmony_ci    parser.add_argument("-mf", "--module_files", nargs='+',
18440681896Sopenharmony_ci                        default=None, help="Module files path.")
18540681896Sopenharmony_ci
18640681896Sopenharmony_ci    args = parser.parse_args(argv)
18740681896Sopenharmony_ci
18840681896Sopenharmony_ci    # Generate the hmp.
18940681896Sopenharmony_ci    build_re = build_hmp(args.package_name, args.out_package, args.pack_info, args.module_files)
19040681896Sopenharmony_ci
19140681896Sopenharmony_ciif __name__ == '__main__':
19240681896Sopenharmony_ci    main(sys.argv[1:])
193