1f6603c60Sopenharmony_ci#!/usr/bin/env python3
2f6603c60Sopenharmony_ci# -*- coding: utf-8 -*-
3f6603c60Sopenharmony_ci#
4f6603c60Sopenharmony_ci# Copyright (c) 2024 Huawei Device Co., Ltd.
5f6603c60Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
6f6603c60Sopenharmony_ci# you may not use this file except in compliance with the License.
7f6603c60Sopenharmony_ci# You may obtain a copy of the License at
8f6603c60Sopenharmony_ci#
9f6603c60Sopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
10f6603c60Sopenharmony_ci#
11f6603c60Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software
12f6603c60Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
13f6603c60Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14f6603c60Sopenharmony_ci# See the License for the specific language governing permissions and
15f6603c60Sopenharmony_ci# limitations under the License.
16f6603c60Sopenharmony_ci#
17f6603c60Sopenharmony_ci
18f6603c60Sopenharmony_ciimport json
19f6603c60Sopenharmony_ciimport os
20f6603c60Sopenharmony_ciimport sys
21f6603c60Sopenharmony_ciimport stat
22f6603c60Sopenharmony_ci
23f6603c60Sopenharmony_ciprecise_repo_xts = sys.argv[1]
24f6603c60Sopenharmony_ciDEEP = int(sys.argv[2]) if len(sys.argv) > 2 else -1
25f6603c60Sopenharmony_cihome = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
26f6603c60Sopenharmony_cimanifest_home = os.path.join(home, ".repo")
27f6603c60Sopenharmony_cipreloader_path = os.path.join(home, "out", "preloader")
28f6603c60Sopenharmony_ciPRECISE_GNI_NAME = "precise_run.gni"
29f6603c60Sopenharmony_ciDEPENDS_TREE_NAME = "depends_tree.txt"
30f6603c60Sopenharmony_ciF_DEPENDS_NAME = "f_depends.txt"
31f6603c60Sopenharmony_ciMAX_PRECISE_PR_NUM = 20
32f6603c60Sopenharmony_ci
33f6603c60Sopenharmony_ci# 首层依赖关系dist
34f6603c60Sopenharmony_cidependency_dist = {}
35f6603c60Sopenharmony_ci# 全量编译白名单
36f6603c60Sopenharmony_ciwhitelist = {"test/xts/acts", "build"}
37f6603c60Sopenharmony_ci
38f6603c60Sopenharmony_ci
39f6603c60Sopenharmony_cidef get_f_dependes_dist(path):
40f6603c60Sopenharmony_ci    count = 0
41f6603c60Sopenharmony_ci    # 遍历目录下的所有文件和子目录
42f6603c60Sopenharmony_ci    for root, dirs, files in os.walk(path):
43f6603c60Sopenharmony_ci        for file in files:
44f6603c60Sopenharmony_ci            if file == 'bundle.json':
45f6603c60Sopenharmony_ci                count = count + 1
46f6603c60Sopenharmony_ci                # 构建完整的文件路径
47f6603c60Sopenharmony_ci                file_path = os.path.join(root, file)
48f6603c60Sopenharmony_ci                # 读取 JSON 文件并转换为 Python 对象
49f6603c60Sopenharmony_ci                with open(file_path, 'r', encoding='utf-8') as f:
50f6603c60Sopenharmony_ci                    json_data = json.load(f)
51f6603c60Sopenharmony_ci                    bundle_name = json_data['name'].split('/')[-1]
52f6603c60Sopenharmony_ci                    if "deps" not in json_data['component']:
53f6603c60Sopenharmony_ci                        continue
54f6603c60Sopenharmony_ci                    deps = json_data['component']['deps']
55f6603c60Sopenharmony_ci                    # 依赖关系额写入dependency_dist
56f6603c60Sopenharmony_ci                    if bundle_name not in dependency_dist:
57f6603c60Sopenharmony_ci                        dependency_dist[bundle_name] = []
58f6603c60Sopenharmony_ci                    if "components" in deps:
59f6603c60Sopenharmony_ci                        components_defs = deps['components']
60f6603c60Sopenharmony_ci                        for c_def in components_defs:
61f6603c60Sopenharmony_ci                            if c_def in dependency_dist:
62f6603c60Sopenharmony_ci                                dependency_dist[c_def].append(bundle_name)
63f6603c60Sopenharmony_ci                            else:
64f6603c60Sopenharmony_ci                                dependency_dist[c_def] = [bundle_name]
65f6603c60Sopenharmony_ci                    if "third_party" in deps:
66f6603c60Sopenharmony_ci                        third_party_defs = deps['third_party']
67f6603c60Sopenharmony_ci                        for t_def in third_party_defs:
68f6603c60Sopenharmony_ci                            if t_def in dependency_dist:
69f6603c60Sopenharmony_ci                                dependency_dist[t_def].append(bundle_name)
70f6603c60Sopenharmony_ci                            else:
71f6603c60Sopenharmony_ci                                dependency_dist[t_def] = [bundle_name]
72f6603c60Sopenharmony_ci    print(count)
73f6603c60Sopenharmony_ci
74f6603c60Sopenharmony_ci
75f6603c60Sopenharmony_cidef getbundname(path_list):
76f6603c60Sopenharmony_ci    print(path_list)
77f6603c60Sopenharmony_ci    bundle_list = []
78f6603c60Sopenharmony_ci    for path in path_list:
79f6603c60Sopenharmony_ci        # 读取JSON文件并获取指定key的value
80f6603c60Sopenharmony_ci        with open(os.path.join(home, path, "bundle.json"), 'r') as file:
81f6603c60Sopenharmony_ci            data = json.load(file)
82f6603c60Sopenharmony_ci        bundle_list.append(data['component']['name'])
83f6603c60Sopenharmony_ci    return bundle_list
84f6603c60Sopenharmony_ci
85f6603c60Sopenharmony_ci
86f6603c60Sopenharmony_cidef get_all_dependencies(nodes, dependencies):
87f6603c60Sopenharmony_ci    visited = set()  # 存储已访问的节点
88f6603c60Sopenharmony_ci    string_buffer = []
89f6603c60Sopenharmony_ci
90f6603c60Sopenharmony_ci    def dfs(node, num, string_buffer):
91f6603c60Sopenharmony_ci        string_buffer.append("  " * num + node)  # 追加内容到列表
92f6603c60Sopenharmony_ci        if node in visited:
93f6603c60Sopenharmony_ci            return
94f6603c60Sopenharmony_ci        if DEEP != -1 and num > DEEP:
95f6603c60Sopenharmony_ci            return
96f6603c60Sopenharmony_ci        visited.add(node)
97f6603c60Sopenharmony_ci        if node in dependencies:
98f6603c60Sopenharmony_ci            for dependency in dependencies[node]:
99f6603c60Sopenharmony_ci                dfs(dependency, num + 1, string_buffer)  # 传递可变对象进行修改
100f6603c60Sopenharmony_ci
101f6603c60Sopenharmony_ci    for node in nodes:
102f6603c60Sopenharmony_ci        dfs(node, 0, string_buffer)
103f6603c60Sopenharmony_ci
104f6603c60Sopenharmony_ci    return visited, string_buffer
105f6603c60Sopenharmony_ci
106f6603c60Sopenharmony_ci
107f6603c60Sopenharmony_cidef write_precise_gni(depends_list, file_name):
108f6603c60Sopenharmony_ci    # 将数组转换为字符串形式,例如使用逗号分隔
109f6603c60Sopenharmony_ci    array_str = json.dumps(list(depends_list))
110f6603c60Sopenharmony_ci
111f6603c60Sopenharmony_ci    # 打开文件并写入数组字符串
112f6603c60Sopenharmony_ci    file_descriptor = os.open(file_name, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP)
113f6603c60Sopenharmony_ci    with os.fdopen(file_descriptor, 'w') as file:
114f6603c60Sopenharmony_ci        file.write("precise_run=")
115f6603c60Sopenharmony_ci        file.write(array_str)
116f6603c60Sopenharmony_ci
117f6603c60Sopenharmony_ci
118f6603c60Sopenharmony_cidef write_file(depends_list, file_name):
119f6603c60Sopenharmony_ci    file_descriptor = os.open(file_name, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP)
120f6603c60Sopenharmony_ci    with os.fdopen(file_descriptor, 'w') as f:
121f6603c60Sopenharmony_ci        json.dump(depends_list, f, indent=4)
122f6603c60Sopenharmony_ci
123f6603c60Sopenharmony_ci
124f6603c60Sopenharmony_cidef run(precise_repo_xts_list):
125f6603c60Sopenharmony_ci    # pr数>MAX或在白名单中的
126f6603c60Sopenharmony_ci    if len(precise_repo_xts_list) >= MAX_PRECISE_PR_NUM or any(item in precise_repo_xts_list for item in whitelist):
127f6603c60Sopenharmony_ci        depends_tree = "all"
128f6603c60Sopenharmony_ci        depends_list = {"all"}
129f6603c60Sopenharmony_ci    else:
130f6603c60Sopenharmony_ci        try:
131f6603c60Sopenharmony_ci            # 获取bundle_name_list
132f6603c60Sopenharmony_ci            bundlelist = getbundname(precise_repo_xts_list)
133f6603c60Sopenharmony_ci            # 计算首层依赖map
134f6603c60Sopenharmony_ci            get_f_dependes_dist(home)
135f6603c60Sopenharmony_ci            print(bundlelist)
136f6603c60Sopenharmony_ci            # 获取全部需要跑的bundlename
137f6603c60Sopenharmony_ci            depends_list, depends_tree = get_all_dependencies(bundlelist, dependency_dist)
138f6603c60Sopenharmony_ci            depends_list.add("acts")
139f6603c60Sopenharmony_ci            print(depends_list)
140f6603c60Sopenharmony_ci        except Exception as e:
141f6603c60Sopenharmony_ci            print("发生异常:", str(e))
142f6603c60Sopenharmony_ci            depends_tree = "all"
143f6603c60Sopenharmony_ci            depends_list = {"all"}
144f6603c60Sopenharmony_ci    # 依赖树输出
145f6603c60Sopenharmony_ci    write_file(depends_tree, os.path.join(preloader_path, DEPENDS_TREE_NAME))
146f6603c60Sopenharmony_ci    # 写入gni文件
147f6603c60Sopenharmony_ci    write_precise_gni(depends_list, os.path.join(preloader_path, PRECISE_GNI_NAME))
148f6603c60Sopenharmony_ci
149f6603c60Sopenharmony_ci
150f6603c60Sopenharmony_ciif __name__ == '__main__':
151f6603c60Sopenharmony_ci    print("counting dependencies start")
152f6603c60Sopenharmony_ci    run(precise_repo_xts.split(','))
153f6603c60Sopenharmony_ci    print("counting dependencies finished")