1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4#
5# Copyright (c) 2023 Huawei Device Co., Ltd.
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17
18import os
19import re
20import sys
21
22from resources.global_var import CURRENT_OHOS_ROOT
23from resources.global_var import COMPONENTS_PATH_DIR
24from exceptions.ohos_exception import OHOSException
25from util.io_util import IoUtil
26from containers.status import throw_exception
27
28
29def get_part_name():
30    part_name_list = []
31    if len(sys.argv) > 2 and not sys.argv[2].startswith("-"):
32        for name in sys.argv[2:]:
33            if not name.startswith('-'):
34                part_name_list.append(name)
35            else:
36                break
37    return part_name_list
38
39
40class ComponentUtil():
41
42    @staticmethod
43    def is_in_component_dir(path: str) -> bool:
44        return _recurrent_search_bundle_file(path)[0]
45
46    @staticmethod
47    def is_component_in_product(component_name: str, product_name: str) -> bool:
48        build_configs_path = os.path.join(
49            CURRENT_OHOS_ROOT, 'out', product_name, 'build_configs')
50        if os.path.exists(build_configs_path):
51            for root, dirs, files in os.walk(build_configs_path, topdown=True, followlinks=False):
52                if component_name in dirs:
53                    return True
54        return False
55
56    @staticmethod
57    def get_component_name(path: str) -> str:
58        found_bundle_file, bundle_path = _recurrent_search_bundle_file(path)
59        if found_bundle_file:
60            data = IoUtil.read_json_file(bundle_path)
61            return data['component']['name']
62
63        return ''
64
65    @staticmethod
66    def get_component(path: str) -> str:
67        found_bundle_file, bundle_path = _recurrent_search_bundle_file(path)
68        if found_bundle_file:
69            data = IoUtil.read_json_file(bundle_path)
70            return data['component']['name'], os.path.dirname(bundle_path)
71
72        return '', ''
73
74    @staticmethod
75    def get_default_deps(variant: str) -> str:
76        gen_default_deps_json(variant, CURRENT_OHOS_ROOT)
77        default_deps_path = os.path.join(
78            CURRENT_OHOS_ROOT, 'out', 'preloader', 'default_deps.json')
79        return default_deps_path
80
81    @staticmethod
82    @throw_exception
83    def get_component_module_full_name(out_path: str, component_name: str, module_name: str) -> str:
84        root_path = os.path.join(out_path, "build_configs")
85        target_info = ""
86        module_list = []
87        for file in os.listdir(root_path):
88            if len(target_info):
89                break
90            file_path = os.path.join(root_path, file)
91            if not os.path.isdir(file_path):
92                continue
93            for component in os.listdir(file_path):
94                if os.path.isdir(os.path.join(file_path, component)) and component == component_name:
95                    target_info = IoUtil.read_file(
96                        os.path.join(file_path, component, "BUILD.gn"))
97                    break
98        pattern = re.compile(r'(?<=module_list = )\[([^\[\]]*)\]')
99        results = pattern.findall(target_info)
100        for each_tuple in results:
101            module_list = each_tuple.replace('\n', '').replace(
102                ' ', '').replace('\"', '').split(',')
103        for target_path in module_list:
104            if target_path != '':
105                path, target = target_path.split(":")
106                if target == module_name:
107                    return target_path
108
109        raise OHOSException('You are trying to compile a module {} which do not exists in {} while compiling {}'.format(
110            module_name, component_name, out_path), "4001")
111
112    @staticmethod
113    def search_bundle_file(component_name: str):
114        all_bundle_path = get_all_bundle_path(CURRENT_OHOS_ROOT)
115        return all_bundle_path.get(component_name)
116
117
118def _recurrent_search_bundle_file(path: str):
119    cur_dir = path
120    while cur_dir != CURRENT_OHOS_ROOT:
121        bundle_json = os.path.join(
122            cur_dir, 'bundle.json')
123        if os.path.exists(bundle_json):
124            return True, bundle_json
125        cur_dir = os.path.dirname(cur_dir)
126    return False, ''
127
128
129def get_all_bundle_path(path):
130    bundles_path = {}
131    for root, dirnames, filenames in os.walk(path):
132        if root == os.path.join(path, "out") or root == os.path.join(path, ".repo"):
133            continue
134        for filename in filenames:
135            if filename == "bundle.json":
136                bundle_json = os.path.join(root, filename)
137                data = IoUtil.read_json_file(bundle_json)
138                bundles_path = process_bundle_path(bundle_json, bundles_path, data)
139    IoUtil.dump_json_file(COMPONENTS_PATH_DIR, bundles_path)
140    return bundles_path
141
142
143def process_bundle_path(bundle_json, bundles_path, data):
144    if data.get("component") and data.get("component").get("name"):
145        bundles_path[data["component"]["name"]] = os.path.dirname(bundle_json)
146    return bundles_path
147
148
149def gen_default_deps_json(variant, root_path):
150    part_name_list = get_part_name()
151    default_deps_out_file = os.path.join(root_path, "out", "preloader", "default_deps.json")
152    default_deps_file = os.path.join(root_path, "build", "indep_configs", "variants", "common", 'default_deps.json')
153    default_deps_json = IoUtil.read_json_file(default_deps_file)
154    default_deps_json.append("variants_" + variant)
155
156    part_white_list_path = os.path.join(root_path, "build", "indep_configs", "config",
157                                        "rust_download_part_whitelist.json")
158    part_white_list = IoUtil.read_json_file(part_white_list_path)
159    for part_name in part_name_list:
160        if part_name in part_white_list and 'rust' not in default_deps_json:
161            default_deps_json.append('rust')
162
163    preloader_path = os.path.join(root_path, "out", "preloader")
164    os.makedirs(preloader_path, exist_ok=True)
165    IoUtil.dump_json_file(default_deps_out_file, default_deps_json)
166