15f9996aaSopenharmony_ci#!/usr/bin/env python 25f9996aaSopenharmony_ci# -*- coding: utf-8 -*- 35f9996aaSopenharmony_ci# Copyright (c) 2021 Huawei Device Co., Ltd. 45f9996aaSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 55f9996aaSopenharmony_ci# you may not use this file except in compliance with the License. 65f9996aaSopenharmony_ci# You may obtain a copy of the License at 75f9996aaSopenharmony_ci# 85f9996aaSopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 95f9996aaSopenharmony_ci# 105f9996aaSopenharmony_ci# Unless required by applicable law or agreed to in writing, software 115f9996aaSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 125f9996aaSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135f9996aaSopenharmony_ci# See the License for the specific language governing permissions and 145f9996aaSopenharmony_ci# limitations under the License. 155f9996aaSopenharmony_ci 165f9996aaSopenharmony_ciimport sys 175f9996aaSopenharmony_ciimport argparse 185f9996aaSopenharmony_ciimport os 195f9996aaSopenharmony_ciimport shutil 205f9996aaSopenharmony_ciimport stat 215f9996aaSopenharmony_ci 225f9996aaSopenharmony_cisys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) 235f9996aaSopenharmony_cifrom scripts.util.file_utils import read_json_file, write_json_file # noqa: E402 245f9996aaSopenharmony_cifrom scripts.util import build_utils # noqa: E402 255f9996aaSopenharmony_ci 265f9996aaSopenharmony_ciREADME_FILE_NAME = 'README.OpenSource' 275f9996aaSopenharmony_ciLICENSE_CANDIDATES = [ 285f9996aaSopenharmony_ci 'LICENSE', 295f9996aaSopenharmony_ci 'License', 305f9996aaSopenharmony_ci 'NOTICE', 315f9996aaSopenharmony_ci 'Notice', 325f9996aaSopenharmony_ci 'COPYRIGHT', 335f9996aaSopenharmony_ci 'Copyright', 345f9996aaSopenharmony_ci 'COPYING', 355f9996aaSopenharmony_ci 'Copying' 365f9996aaSopenharmony_ci] 375f9996aaSopenharmony_ci 385f9996aaSopenharmony_ci 395f9996aaSopenharmony_cidef is_top_dir(current_dir: str): 405f9996aaSopenharmony_ci return os.path.exists(os.path.join(current_dir, '.gn')) 415f9996aaSopenharmony_ci 425f9996aaSopenharmony_ci 435f9996aaSopenharmony_cidef find_other_files(license_file_path): 445f9996aaSopenharmony_ci other_files = [] 455f9996aaSopenharmony_ci if os.path.isfile(license_file_path): 465f9996aaSopenharmony_ci license_dir = os.path.dirname(license_file_path) 475f9996aaSopenharmony_ci license_file = os.path.basename(license_file_path) 485f9996aaSopenharmony_ci for file in LICENSE_CANDIDATES: 495f9996aaSopenharmony_ci license_path = os.path.join(license_dir, file) 505f9996aaSopenharmony_ci if os.path.isfile(license_path) and file != license_file and \ 515f9996aaSopenharmony_ci license_path not in other_files: 525f9996aaSopenharmony_ci other_files.append(license_path) 535f9996aaSopenharmony_ci elif os.path.isdir(license_file_path): 545f9996aaSopenharmony_ci for file in ['COPYRIGHT', 'Copyright', 'COPYING', 'Copying']: 555f9996aaSopenharmony_ci license_file = os.path.join(license_file_path, file) 565f9996aaSopenharmony_ci if os.path.isfile(license_file): 575f9996aaSopenharmony_ci other_files.append(license_file) 585f9996aaSopenharmony_ci return other_files 595f9996aaSopenharmony_ci 605f9996aaSopenharmony_ci 615f9996aaSopenharmony_cidef find_file_recursively(current_dir: str, target_files: list): 625f9996aaSopenharmony_ci if is_top_dir(current_dir): 635f9996aaSopenharmony_ci return None 645f9996aaSopenharmony_ci for file in target_files: 655f9996aaSopenharmony_ci candidate = os.path.join(current_dir, file) 665f9996aaSopenharmony_ci if os.path.isfile(candidate): 675f9996aaSopenharmony_ci return candidate 685f9996aaSopenharmony_ci return find_file_recursively(os.path.dirname(current_dir), target_files) 695f9996aaSopenharmony_ci 705f9996aaSopenharmony_ci 715f9996aaSopenharmony_cidef find_license(current_dir: str): 725f9996aaSopenharmony_ci return find_file_recursively(current_dir, LICENSE_CANDIDATES) 735f9996aaSopenharmony_ci 745f9996aaSopenharmony_ci 755f9996aaSopenharmony_cidef find_opensource(current_dir: str): 765f9996aaSopenharmony_ci return find_file_recursively(current_dir, [README_FILE_NAME]) 775f9996aaSopenharmony_ci 785f9996aaSopenharmony_ci 795f9996aaSopenharmony_cidef get_license_from_readme(readme_path: str): 805f9996aaSopenharmony_ci contents = read_json_file(readme_path) 815f9996aaSopenharmony_ci if contents is None: 825f9996aaSopenharmony_ci raise Exception("Error: failed to read {}.".format(readme_path)) 835f9996aaSopenharmony_ci 845f9996aaSopenharmony_ci if len(contents) <= 1: 855f9996aaSopenharmony_ci notice_file = contents[0].get('License File').strip() 865f9996aaSopenharmony_ci notice_name = contents[0].get('Name').strip() 875f9996aaSopenharmony_ci notice_version = contents[0].get('Version Number').strip() 885f9996aaSopenharmony_ci if notice_file is None: 895f9996aaSopenharmony_ci raise Exception("Error: value of notice file is empty in {}.".format( 905f9996aaSopenharmony_ci readme_path)) 915f9996aaSopenharmony_ci if notice_name is None: 925f9996aaSopenharmony_ci raise Exception("Error: Name of notice file is empty in {}.".format( 935f9996aaSopenharmony_ci readme_path)) 945f9996aaSopenharmony_ci if notice_version is None: 955f9996aaSopenharmony_ci raise Exception("Error: Version Number of notice file is empty in {}.".format( 965f9996aaSopenharmony_ci readme_path)) 975f9996aaSopenharmony_ci 985f9996aaSopenharmony_ci return os.path.join(os.path.dirname(readme_path), notice_file), notice_name, notice_version 995f9996aaSopenharmony_ci else: 1005f9996aaSopenharmony_ci notice_files = [] 1015f9996aaSopenharmony_ci notice_names = [] 1025f9996aaSopenharmony_ci notice_versions = [] 1035f9996aaSopenharmony_ci for content in contents: 1045f9996aaSopenharmony_ci notice_files.append(content.get('License File').strip()) 1055f9996aaSopenharmony_ci notice_names.append(content.get('Name').strip()) 1065f9996aaSopenharmony_ci notice_versions.append(content.get('Version Number').strip()) 1075f9996aaSopenharmony_ci 1085f9996aaSopenharmony_ci if notice_files is None: 1095f9996aaSopenharmony_ci raise Exception("Error: value of notice file is empty in {}.".format( 1105f9996aaSopenharmony_ci readme_path)) 1115f9996aaSopenharmony_ci if notice_names is None: 1125f9996aaSopenharmony_ci raise Exception("Error: Name of notice file is empty in {}.".format( 1135f9996aaSopenharmony_ci readme_path)) 1145f9996aaSopenharmony_ci if notice_versions is None: 1155f9996aaSopenharmony_ci raise Exception("Error: Version Number of notice file is empty in {}.".format( 1165f9996aaSopenharmony_ci readme_path)) 1175f9996aaSopenharmony_ci 1185f9996aaSopenharmony_ci return [os.path.join(os.path.dirname(readme_path), file) for file in notice_files], \ 1195f9996aaSopenharmony_ci notice_names, notice_versions 1205f9996aaSopenharmony_ci 1215f9996aaSopenharmony_ci 1225f9996aaSopenharmony_cidef add_path_to_module_notice(module_notice_info, module_notice_info_list, options): 1235f9996aaSopenharmony_ci if isinstance(module_notice_info.get('Software', None), list): 1245f9996aaSopenharmony_ci softwares = module_notice_info.get('Software') 1255f9996aaSopenharmony_ci versions = module_notice_info.get('Version') 1265f9996aaSopenharmony_ci for software, version in zip(softwares, versions): 1275f9996aaSopenharmony_ci module_notice_info_list.append({'Software': software, 'Version': version}) 1285f9996aaSopenharmony_ci module_notice_info_list[-1]['Path'] = "/{}".format(options.module_source_dir[5:]) 1295f9996aaSopenharmony_ci else: 1305f9996aaSopenharmony_ci if module_notice_info.get('Software', None): 1315f9996aaSopenharmony_ci module_notice_info['Path'] = "/{}".format(options.module_source_dir[5:]) 1325f9996aaSopenharmony_ci module_notice_info_list.append(module_notice_info) 1335f9996aaSopenharmony_ci if module_notice_info_list: 1345f9996aaSopenharmony_ci for module_notice_info in module_notice_info_list: 1355f9996aaSopenharmony_ci module_path = module_notice_info.get("Path", None) 1365f9996aaSopenharmony_ci if module_path is not None: 1375f9996aaSopenharmony_ci module_notice_info["Path"] = module_path.replace("../", "") 1385f9996aaSopenharmony_ci 1395f9996aaSopenharmony_ci 1405f9996aaSopenharmony_cidef do_collect_notice_files(options, depfiles: str): 1415f9996aaSopenharmony_ci module_notice_info_list = [] 1425f9996aaSopenharmony_ci module_notice_info = {} 1435f9996aaSopenharmony_ci notice_file = options.license_file 1445f9996aaSopenharmony_ci other_files = [] 1455f9996aaSopenharmony_ci if notice_file: 1465f9996aaSopenharmony_ci opensource_file = find_opensource(os.path.abspath(options.module_source_dir)) 1475f9996aaSopenharmony_ci if opensource_file is not None and os.path.exists(opensource_file): 1485f9996aaSopenharmony_ci other_files.extend(find_other_files(opensource_file)) 1495f9996aaSopenharmony_ci notice_file_info = get_license_from_readme(opensource_file) 1505f9996aaSopenharmony_ci module_notice_info['Software'] = notice_file_info[1] 1515f9996aaSopenharmony_ci module_notice_info['Version'] = notice_file_info[2] 1525f9996aaSopenharmony_ci else: 1535f9996aaSopenharmony_ci module_notice_info['Software'] = "" 1545f9996aaSopenharmony_ci module_notice_info['Version'] = "" 1555f9996aaSopenharmony_ci if notice_file is None: 1565f9996aaSopenharmony_ci readme_path = os.path.join(options.module_source_dir, 1575f9996aaSopenharmony_ci README_FILE_NAME) 1585f9996aaSopenharmony_ci if not os.path.exists(readme_path): 1595f9996aaSopenharmony_ci readme_path = find_opensource(os.path.abspath(options.module_source_dir)) 1605f9996aaSopenharmony_ci other_files.extend(find_other_files(options.module_source_dir)) 1615f9996aaSopenharmony_ci if readme_path is not None: 1625f9996aaSopenharmony_ci depfiles.append(readme_path) 1635f9996aaSopenharmony_ci notice_file_info = get_license_from_readme(readme_path) 1645f9996aaSopenharmony_ci notice_file = notice_file_info[0] 1655f9996aaSopenharmony_ci if isinstance(notice_file, list): 1665f9996aaSopenharmony_ci notice_file = ",".join(notice_file) 1675f9996aaSopenharmony_ci module_notice_info['Software'] = notice_file_info[1] 1685f9996aaSopenharmony_ci module_notice_info['Version'] = notice_file_info[2] 1695f9996aaSopenharmony_ci 1705f9996aaSopenharmony_ci if notice_file is None: 1715f9996aaSopenharmony_ci notice_file = find_license(options.module_source_dir) 1725f9996aaSopenharmony_ci opensource_file = find_opensource(os.path.abspath(options.module_source_dir)) 1735f9996aaSopenharmony_ci if opensource_file is not None and os.path.exists(opensource_file): 1745f9996aaSopenharmony_ci other_files.extend(find_other_files(opensource_file)) 1755f9996aaSopenharmony_ci notice_file_info = get_license_from_readme(opensource_file) 1765f9996aaSopenharmony_ci module_notice_info['Software'] = notice_file_info[1] 1775f9996aaSopenharmony_ci module_notice_info['Version'] = notice_file_info[2] 1785f9996aaSopenharmony_ci else: 1795f9996aaSopenharmony_ci module_notice_info['Software'] = "" 1805f9996aaSopenharmony_ci module_notice_info['Version'] = "" 1815f9996aaSopenharmony_ci 1825f9996aaSopenharmony_ci add_path_to_module_notice(module_notice_info, module_notice_info_list, options) 1835f9996aaSopenharmony_ci 1845f9996aaSopenharmony_ci if notice_file: 1855f9996aaSopenharmony_ci if other_files: 1865f9996aaSopenharmony_ci notice_file = f"{notice_file},{','.join(other_files)}" 1875f9996aaSopenharmony_ci for output in options.output: 1885f9996aaSopenharmony_ci notice_info_json = '{}.json'.format(output) 1895f9996aaSopenharmony_ci os.makedirs(os.path.dirname(output), exist_ok=True) 1905f9996aaSopenharmony_ci os.makedirs(os.path.dirname(notice_info_json), exist_ok=True) 1915f9996aaSopenharmony_ci notice_files = [file for file in notice_file.split(",") if file] 1925f9996aaSopenharmony_ci 1935f9996aaSopenharmony_ci write_file_content(notice_files, options, output, notice_info_json, module_notice_info_list, depfiles) 1945f9996aaSopenharmony_ci 1955f9996aaSopenharmony_ci 1965f9996aaSopenharmony_cidef write_file_content(notice_files, options, output, notice_info_json, module_notice_info_list, depfiles): 1975f9996aaSopenharmony_ci for notice_file in notice_files: 1985f9996aaSopenharmony_ci notice_file = notice_file.strip() 1995f9996aaSopenharmony_ci if not os.path.exists(notice_file): 2005f9996aaSopenharmony_ci notice_file = os.path.join(options.module_source_dir, notice_file) 2015f9996aaSopenharmony_ci if os.path.exists(notice_file): 2025f9996aaSopenharmony_ci if not os.path.exists(output): 2035f9996aaSopenharmony_ci build_utils.touch(output) 2045f9996aaSopenharmony_ci write_notice_to_output(notice_file, output) 2055f9996aaSopenharmony_ci write_json_file(notice_info_json, module_notice_info_list) 2065f9996aaSopenharmony_ci else: 2075f9996aaSopenharmony_ci build_utils.touch(output) 2085f9996aaSopenharmony_ci build_utils.touch(notice_info_json) 2095f9996aaSopenharmony_ci depfiles.append(notice_file) 2105f9996aaSopenharmony_ci 2115f9996aaSopenharmony_ci 2125f9996aaSopenharmony_cidef write_notice_to_output(notice_file, output): 2135f9996aaSopenharmony_ci with os.fdopen(os.open(notice_file, os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR), 2145f9996aaSopenharmony_ci 'r', encoding='utf-8', errors='ignore') as notice_data_flow: 2155f9996aaSopenharmony_ci license_content = notice_data_flow.read() 2165f9996aaSopenharmony_ci with os.fdopen(os.open(output, os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR), 2175f9996aaSopenharmony_ci 'r', encoding='utf-8', errors='ignore') as output_data_flow: 2185f9996aaSopenharmony_ci output_file_content = output_data_flow.read() 2195f9996aaSopenharmony_ci if license_content not in output_file_content: 2205f9996aaSopenharmony_ci with os.fdopen(os.open(output, os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR), 2215f9996aaSopenharmony_ci 'a', encoding='utf-8') as testfwk_info_file: 2225f9996aaSopenharmony_ci testfwk_info_file.write(f"{license_content}\n") 2235f9996aaSopenharmony_ci testfwk_info_file.close() 2245f9996aaSopenharmony_ci 2255f9996aaSopenharmony_ci 2265f9996aaSopenharmony_cidef main(args): 2275f9996aaSopenharmony_ci args = build_utils.expand_file_args(args) 2285f9996aaSopenharmony_ci 2295f9996aaSopenharmony_ci parser = argparse.ArgumentParser() 2305f9996aaSopenharmony_ci build_utils.add_depfile_option(parser) 2315f9996aaSopenharmony_ci 2325f9996aaSopenharmony_ci parser.add_argument('--license-file', required=False) 2335f9996aaSopenharmony_ci parser.add_argument('--output', action='append', required=False) 2345f9996aaSopenharmony_ci parser.add_argument('--sources', action='append', required=False) 2355f9996aaSopenharmony_ci parser.add_argument('--sdk-install-info-file', required=False) 2365f9996aaSopenharmony_ci parser.add_argument('--label', required=False) 2375f9996aaSopenharmony_ci parser.add_argument('--sdk-notice-dir', required=False) 2385f9996aaSopenharmony_ci parser.add_argument('--module-source-dir', 2395f9996aaSopenharmony_ci help='source directory of this module', 2405f9996aaSopenharmony_ci required=True) 2415f9996aaSopenharmony_ci 2425f9996aaSopenharmony_ci options = parser.parse_args() 2435f9996aaSopenharmony_ci depfiles = [] 2445f9996aaSopenharmony_ci 2455f9996aaSopenharmony_ci if options.sdk_install_info_file: 2465f9996aaSopenharmony_ci install_dir = '' 2475f9996aaSopenharmony_ci sdk_install_info = read_json_file(options.sdk_install_info_file) 2485f9996aaSopenharmony_ci for item in sdk_install_info: 2495f9996aaSopenharmony_ci if options.label == item.get('label'): 2505f9996aaSopenharmony_ci install_dir = item.get('install_dir') 2515f9996aaSopenharmony_ci break 2525f9996aaSopenharmony_ci if options.sources and install_dir: 2535f9996aaSopenharmony_ci for src in options.sources: 2545f9996aaSopenharmony_ci extend_output = os.path.join(options.sdk_notice_dir, install_dir, 2555f9996aaSopenharmony_ci '{}.{}'.format(os.path.basename(src), 'txt')) 2565f9996aaSopenharmony_ci options.output.append(extend_output) 2575f9996aaSopenharmony_ci 2585f9996aaSopenharmony_ci do_collect_notice_files(options, depfiles) 2595f9996aaSopenharmony_ci if options.license_file: 2605f9996aaSopenharmony_ci depfiles.append(options.license_file) 2615f9996aaSopenharmony_ci build_utils.write_depfile(options.depfile, options.output[0], depfiles) 2625f9996aaSopenharmony_ci 2635f9996aaSopenharmony_ci 2645f9996aaSopenharmony_ciif __name__ == '__main__': 2655f9996aaSopenharmony_ci sys.exit(main(sys.argv[1:])) 2665f9996aaSopenharmony_ci 267