1 #!/usr/bin/env python3 2 # -*- coding: utf-8 -*- 3 4 # Copyright (c) 2023 Huawei Device Co., Ltd. 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 """ 18 The tool for making hmp. 19 20 positional arguments: 21 -pn PACKAGE_NAME, --package_name PACKAGE_NAME 22 Module package name. 23 -op OUT_PACKAGE, --out_package OUT_PACKAGE 24 Out package file path. 25 -pi PACK_INFO, --pack_info PACK_INFO 26 Pack info file path. 27 -mf MODULE_FILES, --module_files MODULE_FILES 28 Module files path. 29 """ 30 import os 31 import sys 32 import argparse 33 import zipfile 34 import io 35 import logging 36 37 38 # 1000000: max number of function recursion depth 39 MAXIMUM_RECURSION_DEPTH = 1000000 40 sys.setrecursionlimit(MAXIMUM_RECURSION_DEPTH) 41 42 43 def package_name_check(arg): 44 """ 45 Argument check, which is used to check whether the specified arg is none. 46 :param arg: the arg to check 47 :return: Check result, which is False if the arg is invalid. 48 """ 49 if arg is None: 50 UPDATE_LOGGER.print_log( 51 "Package name error: %s" % arg, UPDATE_LOGGER.ERROR_LOG) 52 return False 53 return arg 54 55 56 def check_out_package(arg): 57 """ 58 Argument check, which is used to check whether 59 the update package path exists. 60 :param arg: The arg to check. 61 :return: Check result 62 """ 63 make_dir_path = None 64 if os.path.exists(arg): 65 if os.path.isfile(arg): 66 UPDATE_LOGGER.print_log( 67 "Out package must be a dir path, not a file path. " 68 "path: %s" % arg, UPDATE_LOGGER.ERROR_LOG) 69 return False 70 else: 71 try: 72 UPDATE_LOGGER.print_log( 73 "Out package path does not exist. The dir will be created!" 74 "path: %s" % arg, UPDATE_LOGGER.WARNING_LOG) 75 os.makedirs(arg) 76 make_dir_path = arg 77 except OSError: 78 UPDATE_LOGGER.print_log( 79 "Make out package path dir failed! " 80 "path: %s" % arg, UPDATE_LOGGER.ERROR_LOG) 81 return False 82 return arg 83 84 85 def pack_info_check(arg): 86 """ 87 Argument check, which is used to check whether 88 the specified arg is a pack info. 89 :param arg: the arg to check 90 :return: Check result, which is False if the arg is invalid. 91 """ 92 if not os.path.isfile(arg): 93 UPDATE_LOGGER.print_log( 94 "FileNotFoundError, path: %s" % arg, UPDATE_LOGGER.ERROR_LOG) 95 return False 96 return arg 97 98 99 class UpdateToolLogger: 100 """ 101 Global log class 102 """ 103 INFO_LOG = 'INFO_LOG' 104 WARNING_LOG = 'WARNING_LOG' 105 ERROR_LOG = 'ERROR_LOG' 106 LOG_TYPE = (INFO_LOG, WARNING_LOG, ERROR_LOG) 107 108 def __init__(self, output_type='console'): 109 self.__logger_obj = self.__get_logger_obj(output_type=output_type) 110 111 @staticmethod 112 def __get_logger_obj(output_type='console'): 113 ota_logger = logging.getLogger(__name__) 114 ota_logger.setLevel(level=logging.INFO) 115 formatter = logging.Formatter( 116 '%(asctime)s %(levelname)s : %(message)s', 117 "%Y-%m-%d %H:%M:%S") 118 if output_type == 'console': 119 console_handler = logging.StreamHandler() 120 console_handler.setLevel(logging.INFO) 121 console_handler.setFormatter(formatter) 122 ota_logger.addHandler(console_handler) 123 elif output_type == 'file': 124 file_handler = logging.FileHandler("UpdateToolLog.txt") 125 file_handler.setLevel(logging.INFO) 126 file_handler.setFormatter(formatter) 127 ota_logger.addHandler(file_handler) 128 return ota_logger 129 130 def print_log(self, msg, log_type=INFO_LOG): 131 """ 132 Print log information. 133 :param msg: log information 134 :param log_type: log type 135 :return: 136 """ 137 if log_type == self.LOG_TYPE[0]: 138 self.__logger_obj.info(msg) 139 elif log_type == self.LOG_TYPE[1]: 140 self.__logger_obj.warning(msg) 141 elif log_type == self.LOG_TYPE[2]: 142 self.__logger_obj.error(msg) 143 else: 144 self.__logger_obj.error("Unknown log type! %s", log_type) 145 return False 146 return True 147 148 def print_uncaught_exception_msg(self, msg, exc_info): 149 """ 150 Print log when an uncaught exception occurs. 151 :param msg: Uncaught exception 152 :param exc_info: information about the uncaught exception 153 """ 154 self.__logger_obj.error(msg, exc_info=exc_info) 155 156 157 UPDATE_LOGGER = UpdateToolLogger() 158 159 160 def build_hmp(package_name, out_package, pack_info, module_files): 161 out_package_path = os.path.join( 162 out_package, '%s.zip' % package_name) 163 zip_file = zipfile.ZipFile(out_package_path, 'w', zipfile.ZIP_DEFLATED, allowZip64=True) 164 for module_file in module_files: 165 zip_file.write(module_file, os.path.basename(module_file)) 166 zip_file.write(pack_info, os.path.basename(pack_info)) 167 zip_file.close() 168 return True 169 170 171 def main(argv): 172 """ 173 Entry function. 174 """ 175 parser = argparse.ArgumentParser() 176 177 parser.add_argument("-pn", "--package_name", type=package_name_check, 178 default=None, help="Module package name.") 179 parser.add_argument("-op", "--out_package", type=check_out_package, 180 default=None, help="Out package file path.") 181 parser.add_argument("-pi", "--pack_info", type=pack_info_check, 182 default=None, help="Pack info file path.") 183 parser.add_argument("-mf", "--module_files", nargs='+', 184 default=None, help="Module files path.") 185 186 args = parser.parse_args(argv) 187 188 # Generate the hmp. 189 build_re = build_hmp(args.package_name, args.out_package, args.pack_info, args.module_files) 190 191 if __name__ == '__main__': 192 main(sys.argv[1:]) 193