1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# Copyright (c) 2022 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 os 17import re 18from bundle_check.bundle_check_common import BundleCheckTools 19from bundle_check.warning_info import BCWarnInfo 20 21 22class BundleCheckOnline: 23 '''用于检查 bundle.json pr。''' 24 25 @staticmethod 26 def check_diff(diff:dict): 27 ''' 28 @func: 根据 diff 部分对 bundle.json 进行静态检查。 29 @parm: 30 ``diff``: 格式化后的字典类型的 diff 文件修改信息。示例: 31 d = { 32 "path1/bundle.json": [ 33 [line1, "content1"], 34 [line2, "content2"] 35 ] 36 } 37 ''' 38 diff_dict = {} 39 for file_path in diff: 40 diff_dict[file_path] = [] 41 diff_list = diff[file_path] 42 for i in diff_list: 43 if '/third_party_' in file_path and 'name' in i[1]: 44 continue 45 ret = BundleCheckOnline.check_diff_by_line(i[1]) 46 if not ret: 47 continue 48 line = list(("line" + str(i[0]) + ": " + i[1], ret)) 49 if file_path in diff_dict.keys(): 50 diff_dict[file_path].append(line) 51 # trans to list 52 err_list = [] 53 for file in diff_dict: 54 for i in diff_dict[file]: 55 row = [file, i[0]] 56 row.extend([BCWarnInfo.CHECK_RULE_2_1, i[1]]) 57 err_list.append(row) 58 if err_list: 59 return True, err_list 60 else: 61 return False, err_list 62 63 def check_diff_by_line(line:str) -> str: 64 line = line.strip() 65 match = re.match(r'"(\w+)"\s*:\s*"(.*)"', line) 66 if not match: 67 return "" 68 key = match.group(1) 69 value = match.group(2) 70 71 if key == 'name': 72 return _check_line_name(value) 73 if key == 'version': 74 if len(value) == 0: 75 return BCWarnInfo.VERSION_EMPTY 76 else: 77 return "" 78 if key == 'destPath': 79 if os.path.isabs(value): 80 return BCWarnInfo.SEGMENT_DESTPATH_ABS 81 return "" 82 if key == 'subsystem': 83 if not re.match(r'[a-z]+$', value): 84 return BCWarnInfo.COMPONENT_SUBSYSTEM_LOWCASE 85 if key == 'rom' or key == 'ram': 86 return _check_line_rom_ram(key, value) 87 if key == 'syscap': 88 return _check_line_syscap(value) 89 if key == 'features': 90 if len(value) == 0: 91 return BCWarnInfo.COMPONENT_FEATURES_STRING_EMPTY 92 return "" 93 94 95def _check_line_name(value: str): 96 if not value: # value empty 97 return BCWarnInfo.NAME_EMPTY 98 if value.startswith('//') and ':' in value: # exclude inner_kits:name 99 return "" 100 if ('/' in value) and (not BundleCheckTools.match_bundle_full_name(value)): 101 return BCWarnInfo.NAME_FORMAT_ERROR + \ 102 BCWarnInfo.COMPONENT_NAME_FROMAT_LEN 103 104 component_name = value.split('/')[1] if ('/' in value) else value 105 if not BundleCheckTools.match_unix_like_name(component_name): 106 return BCWarnInfo.COMPONENT_NAME_FROMAT 107 return "" 108 109 110def _check_line_version(value): 111 if len(value) < 3: 112 return BCWarnInfo.VERSION_ERROR 113 ohos_root_path = BundleCheckTools.get_root_path() 114 if not ohos_root_path: 115 # when project is not exist, do not raise checking error 116 return "" 117 ohos_version = BundleCheckTools.get_ohos_version(ohos_root_path) 118 if ohos_version and value != ohos_version: 119 return BCWarnInfo.VERSION_ERROR + ' ohos version is: ' + value 120 return "" 121 122 123def _check_line_rom_ram(key, value): 124 if len(value) == 0: 125 return r'"component:rom/ram" 字段不能为空。' 126 num, unit = BundleCheckTools.split_by_unit(value) 127 if num < 0: 128 return '"component:{}" 非数值或者小于等于 0。'.format(key) 129 if unit: 130 unit_types = ["KB", "KByte", "MByte", "MB"] 131 if unit not in unit_types: 132 return '"component:{}" 的单位错误(KB, KByte, MByte, MB,默认为KByte)。'.format(key) 133 return "" 134 135 136def _check_line_syscap(value): 137 if len(value) == 0: 138 return BCWarnInfo.COMPONENT_SYSCAP_STRING_EMPTY 139 match = re.match(r'^SystemCapability(\.[A-Z][a-zA-Z]{1,63}){2,6}$', value) 140 if not match: 141 return BCWarnInfo.COMPONENT_SYSCAP_STRING_FORMAT_ERROR 142 return ""