1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# Copyright (c) 2021 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import sys 17import argparse 18import os 19import shutil 20 21sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) 22from scripts.util.file_utils import read_json_file, write_json_file # noqa: E402 23from scripts.util import build_utils # noqa: E402 24 25README_FILE_NAME = 'README.OpenSource' 26LICENSE_CANDIDATES = [ 27 'LICENSE', 28 'License', 29 'NOTICE', 30 'Notice', 31 'COPYRIGHT', 32 'Copyright' 33] 34 35 36def is_top_dir(current_dir): 37 return os.path.exists(os.path.join(current_dir, '.gn')) 38 39 40def find_license_recursively(current_dir, default_license): 41 if is_top_dir(current_dir): 42 return default_license 43 for file in ['LICENSE', 'NOTICE', 'License', 'Copyright']: 44 candidate = os.path.join(current_dir, file) 45 if os.path.isfile(os.path.join(current_dir, file)): 46 return os.path.join(candidate) 47 return find_license_recursively(os.path.dirname(current_dir), 48 default_license) 49 50 51def find_opensource_recursively(current_dir): 52 if is_top_dir(current_dir): 53 return None 54 candidate = os.path.join(current_dir, README_FILE_NAME) 55 if os.path.isfile(candidate): 56 return os.path.join(candidate) 57 return find_opensource_recursively(os.path.dirname(current_dir)) 58 59 60def get_license_from_readme(readme_path): 61 contents = read_json_file(readme_path) 62 if contents is None: 63 raise Exception("Error: failed to read {}.".format(readme_path)) 64 65 notice_file = contents[0].get('License File').strip() 66 notice_name = contents[0].get('Name').strip() 67 notice_version = contents[0].get('Version Number').strip() 68 if notice_file is None: 69 raise Exception("Error: value of notice file is empty in {}.".format( 70 readme_path)) 71 if notice_name is None: 72 raise Exception("Error: Name of notice file is empty in {}.".format( 73 readme_path)) 74 if notice_version is None: 75 raise Exception("Error: Version Number of notice file is empty in {}.".format( 76 readme_path)) 77 78 return os.path.join(os.path.dirname(readme_path), notice_file), notice_name, notice_version 79 80 81def do_collect_notice_files(options, depfiles): 82 module_notice_info_list = [] 83 module_notice_info = {} 84 notice_file = options.license_file 85 if notice_file: 86 opensource_file = find_opensource_recursively(os.path.abspath(options.module_source_dir)) 87 if opensource_file is not None and os.path.exists(opensource_file): 88 notice_file_info = get_license_from_readme(opensource_file) 89 module_notice_info['Software'] = "{} {}".format(notice_file_info[1], notice_file_info[2]) 90 else: 91 module_notice_info['Software'] = "" 92 if notice_file is None: 93 readme_path = os.path.join(options.module_source_dir, 94 README_FILE_NAME) 95 if os.path.exists(readme_path): 96 depfiles.append(readme_path) 97 notice_file_info = get_license_from_readme(readme_path) 98 notice_file = notice_file_info[0] 99 module_notice_info['Software'] = "{} {}".format(notice_file_info[1], notice_file_info[2]) 100 101 if notice_file is None: 102 notice_file = find_license_recursively(options.module_source_dir, 103 options.default_license) 104 opensource_file = find_opensource_recursively(os.path.abspath(options.module_source_dir)) 105 if opensource_file is not None and os.path.exists(opensource_file): 106 notice_file_info = get_license_from_readme(opensource_file) 107 module_notice_info['Software'] = "{} {}".format(notice_file_info[1], notice_file_info[2]) 108 else: 109 module_notice_info['Software'] = "" 110 111 module_notice_info['Path'] = "/{}".format(options.module_source_dir[5:]) 112 module_notice_info_list.append(module_notice_info) 113 114 if notice_file: 115 for output in options.output: 116 notice_info_json = '{}.json'.format(output) 117 os.makedirs(os.path.dirname(output), exist_ok=True) 118 os.makedirs(os.path.dirname(notice_info_json), exist_ok=True) 119 if os.path.exists(notice_file): 120 shutil.copy(notice_file, output) 121 write_json_file(notice_info_json, module_notice_info_list) 122 else: 123 build_utils.touch(output) 124 build_utils.touch(notice_info_json) 125 depfiles.append(notice_file) 126 127 128def main(args): 129 args = build_utils.expand_file_args(args) 130 131 parser = argparse.ArgumentParser() 132 build_utils.add_depfile_option(parser) 133 134 parser.add_argument('--license-file', required=False) 135 parser.add_argument('--default-license', required=True) 136 parser.add_argument('--output', action='append', required=False) 137 parser.add_argument('--module-source-dir', 138 help='source directory of this module', 139 required=True) 140 141 options = parser.parse_args() 142 depfiles = [] 143 144 do_collect_notice_files(options, depfiles) 145 if options.license_file: 146 depfiles.append(options.license_file) 147 build_utils.write_depfile(options.depfile, options.output[0], depfiles) 148 149 150if __name__ == '__main__': 151 sys.exit(main(sys.argv[1:])) 152