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 os 18import shutil 19import tarfile 20import argparse 21from util import build_utils 22 23sys.path.append( 24 os.path.abspath(os.path.dirname(os.path.abspath( 25 os.path.dirname(__file__))))) 26from scripts.util.file_utils import read_json_file # noqa: E402 27 28RELEASE_FILENAME = 'README.OpenSource' 29 30 31def _copy_opensource_file(opensource_config_file: str, top_dir: str, package_dir: str) -> bool: 32 if not os.path.exists(opensource_config_file): 33 print("Warning, the opensource config file is not exists.") 34 return False 35 36 src_dir = os.path.dirname(opensource_config_file) 37 dst_dir = os.path.join(package_dir, os.path.relpath(src_dir, top_dir)) 38 39 # copy opensource folder to out dir 40 if os.path.exists(dst_dir): 41 shutil.rmtree(dst_dir) 42 shutil.copytree(src_dir, 43 dst_dir, 44 symlinks=True, 45 ignore=shutil.ignore_patterns('*.pyc', 'tmp*', '.git*')) 46 47 # delete the README.OpenSource file 48 release_file = os.path.join(dst_dir, RELEASE_FILENAME) 49 os.remove(release_file) 50 return True 51 52 53def _parse_opensource_file(opensource_config_file: str, license_set: set) -> bool: 54 if not os.path.exists(opensource_config_file): 55 print("Warning, the opensource config file is not exists.") 56 return False 57 58 opensource_config = read_json_file(opensource_config_file) 59 if opensource_config is None: 60 raise Exception("read opensource config file [{}] failed.".format( 61 opensource_config_file)) 62 63 result = False 64 for info in opensource_config: 65 _license = info.get('License') 66 # any license in collect list is collected 67 if any(lic in _license for lic in license_set): 68 result = True 69 break 70 71 return result 72 73 74def _scan_and_package_code_release(scan_dir: str, top_dir: str, package_dir: str, license_set: set): 75 file_dir_names = os.listdir(scan_dir) 76 for file_dir_name in file_dir_names: 77 file_dir_path = os.path.join(scan_dir, file_dir_name) 78 if os.path.isdir(file_dir_path) and not os.path.islink(file_dir_path): 79 _scan_and_package_code_release(file_dir_path, top_dir, package_dir, license_set) 80 elif file_dir_path == os.path.join(scan_dir, RELEASE_FILENAME): 81 if _parse_opensource_file(file_dir_path, license_set): 82 _copy_opensource_file(file_dir_path, top_dir, package_dir) 83 84 85def _collect_opensource(options, package_dir: str): 86 # get the source top directory to be scan 87 top_dir = options.root_dir 88 89 # processing scan dir and license, split by colon 90 scan_dir_list = options.scan_dirs.split(":") 91 if not scan_dir_list: 92 raise Exception("empty scan dir, please check the value of osp_scan_dirs.") 93 scan_licenses = options.scan_licenses.split(":") 94 if not scan_licenses: 95 raise Exception("empty scan licenses, please check the value of osp_scan_licenses.") 96 97 # scan the target dir and copy release code to out/opensource dir 98 # remove duplicate scan dir 99 dir_set = set([os.path.join(top_dir, _dir) for _dir in scan_dir_list]) 100 # remove duplicate licenses 101 license_set = set(scan_licenses) 102 for scan_dir in dir_set: 103 if not os.path.isdir(scan_dir): 104 raise Exception(f"{scan_dir} not exist, this is invalid.") 105 _scan_and_package_code_release(scan_dir, top_dir, package_dir, license_set) 106 107 108def _tar_opensource_package_file(options, package_dir: str) -> int: 109 result = -1 110 if os.path.exists(package_dir): 111 try: 112 with tarfile.open(options.output, "w:gz") as tar: 113 tar.add(package_dir, arcname=".") 114 result = 0 115 except IOError as err: 116 raise err 117 return result 118 119 120def main(args) -> int: 121 """generate open source packages to release.""" 122 parser = argparse.ArgumentParser() 123 build_utils.add_depfile_option(parser) 124 parser.add_argument('--output', required=True, help='output') 125 parser.add_argument('--root-dir', required=True, help='source root directory') 126 parser.add_argument('--scan-dirs', required=True, help='extended scan directory') 127 parser.add_argument('--scan-licenses', required=True, help='extended scan licenses') 128 129 # add optional extended parameters 130 parser.add_argument('--only-collect-file', action='store_true', help='need post process, only collect file') 131 132 options = parser.parse_args(args) 133 134 # need post process, only collection is required 135 if options.only_collect_file: 136 package_dir = os.path.dirname(options.output) 137 if os.path.exists(package_dir): 138 shutil.rmtree(package_dir) 139 os.makedirs(package_dir, exist_ok=True) 140 _collect_opensource(options, package_dir) 141 build_utils.touch(options.output) 142 return 0 143 144 with build_utils.temp_dir() as package_dir: 145 _collect_opensource(options, package_dir) 146 # package the opensource to Code_Opensource.tar.gz 147 if _tar_opensource_package_file(options, package_dir) == 0: 148 print('Generate the opensource package successfully.') 149 else: 150 print('Generate the opensource package failed.') 151 152 return 0 153 154 155if __name__ == '__main__': 156 sys.exit(main(sys.argv[1:])) 157