15f9996aaSopenharmony_ci#!/usr/bin/env python3
25f9996aaSopenharmony_ci# -*- coding: utf-8 -*-
35f9996aaSopenharmony_ci# Copyright (c) 2022 Huawei Device Co., Ltd.
45f9996aaSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
55f9996aaSopenharmony_ci# you may not use this file except in compliance with the License.
65f9996aaSopenharmony_ci# You may obtain a copy of the License at
75f9996aaSopenharmony_ci#
85f9996aaSopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
95f9996aaSopenharmony_ci#
105f9996aaSopenharmony_ci# Unless required by applicable law or agreed to in writing, software
115f9996aaSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
125f9996aaSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135f9996aaSopenharmony_ci# See the License for the specific language governing permissions and
145f9996aaSopenharmony_ci# limitations under the License.
155f9996aaSopenharmony_ci
165f9996aaSopenharmony_ciimport argparse
175f9996aaSopenharmony_ciimport os
185f9996aaSopenharmony_ciimport sys
195f9996aaSopenharmony_ciimport stat
205f9996aaSopenharmony_ciimport xml.etree.ElementTree as ET
215f9996aaSopenharmony_ciimport pandas as pd
225f9996aaSopenharmony_cifrom prettytable import PrettyTable
235f9996aaSopenharmony_ci
245f9996aaSopenharmony_cifrom gn_check.check_gn import CheckGn
255f9996aaSopenharmony_cifrom bundle_check.bundle_json_check import BundlesCheck
265f9996aaSopenharmony_ci
275f9996aaSopenharmony_ci
285f9996aaSopenharmony_ciclass CsctGlobal(object):
295f9996aaSopenharmony_ci    """This is a gn variable check class"""
305f9996aaSopenharmony_ci
315f9996aaSopenharmony_ci    version = ""
325f9996aaSopenharmony_ci    csct_path = ""
335f9996aaSopenharmony_ci    ohos_root = ""
345f9996aaSopenharmony_ci    repo_url = ""
355f9996aaSopenharmony_ci    repo_num = ""
365f9996aaSopenharmony_ci    diff_files_path = ""
375f9996aaSopenharmony_ci    output_format = ""
385f9996aaSopenharmony_ci    check_path = ""
395f9996aaSopenharmony_ci    whitelist = ()
405f9996aaSopenharmony_ci
415f9996aaSopenharmony_ci    def __init__(self) -> None:
425f9996aaSopenharmony_ci        version = "0.0.1"
435f9996aaSopenharmony_ci        self.csct_path = sys.path[0]
445f9996aaSopenharmony_ci        root = os.path.join(self.csct_path, "../../../..")
455f9996aaSopenharmony_ci        self.ohos_root = os.path.normpath(root)
465f9996aaSopenharmony_ci        self.whitelist = tuple()
475f9996aaSopenharmony_ci
485f9996aaSopenharmony_ci    def load_ohos_xml(self, path):
495f9996aaSopenharmony_ci        ret_dict = dict()
505f9996aaSopenharmony_ci        tree = ET.parse(path)
515f9996aaSopenharmony_ci        root = tree.getroot()
525f9996aaSopenharmony_ci        for node in root.iter():
535f9996aaSopenharmony_ci            if node.tag != 'project':
545f9996aaSopenharmony_ci                continue
555f9996aaSopenharmony_ci            repo_info = node.attrib
565f9996aaSopenharmony_ci            ret_item = {repo_info['path']: repo_info['groups']}
575f9996aaSopenharmony_ci            ret_dict.update(ret_item)
585f9996aaSopenharmony_ci        return ret_dict
595f9996aaSopenharmony_ci
605f9996aaSopenharmony_ci    def handle_white_dir(self, check_path):
615f9996aaSopenharmony_ci        xml_dict = self.load_ohos_xml(os.path.join(
625f9996aaSopenharmony_ci            self.ohos_root, '.repo/manifests/ohos/ohos.xml'))
635f9996aaSopenharmony_ci        ret_list = ['device', 'vendor', 'build', 'third_party', 'out']
645f9996aaSopenharmony_ci        for key, vlaues in xml_dict.items():
655f9996aaSopenharmony_ci            if key.startswith('third_party'):
665f9996aaSopenharmony_ci                continue
675f9996aaSopenharmony_ci            if vlaues.find('ohos:mini') != -1:
685f9996aaSopenharmony_ci                ret_list.append(key)
695f9996aaSopenharmony_ci            elif vlaues.find('ohos:small') != -1:
705f9996aaSopenharmony_ci                ret_list.append(key)
715f9996aaSopenharmony_ci
725f9996aaSopenharmony_ci        if check_path:
735f9996aaSopenharmony_ci            ret_list = [x[len(check_path) + 1:]
745f9996aaSopenharmony_ci                        for x in ret_list if x.startswith(check_path)]
755f9996aaSopenharmony_ci
765f9996aaSopenharmony_ci        return tuple(ret_list)
775f9996aaSopenharmony_ci
785f9996aaSopenharmony_ci    def add_option(self, parser):
795f9996aaSopenharmony_ci        parser.add_argument(
805f9996aaSopenharmony_ci            "-w",
815f9996aaSopenharmony_ci            "--white_dir_on",
825f9996aaSopenharmony_ci            dest="white_dir_settings",
835f9996aaSopenharmony_ci            type=str,
845f9996aaSopenharmony_ci            default="on",
855f9996aaSopenharmony_ci            choices=["on", "off"],
865f9996aaSopenharmony_ci            help="turn on white dir function or not",
875f9996aaSopenharmony_ci        )
885f9996aaSopenharmony_ci        parser.add_argument(
895f9996aaSopenharmony_ci            "-v", "--version", action="version", version=f"%(prog)s {self.version}."
905f9996aaSopenharmony_ci        )
915f9996aaSopenharmony_ci        parser.add_argument(
925f9996aaSopenharmony_ci            "-gd",
935f9996aaSopenharmony_ci            "--generate_diff",
945f9996aaSopenharmony_ci            metavar=("repo", "prNum"),
955f9996aaSopenharmony_ci            dest="repo_pr",
965f9996aaSopenharmony_ci            nargs=2,
975f9996aaSopenharmony_ci            type=str,
985f9996aaSopenharmony_ci            help="generate diff files.",
995f9996aaSopenharmony_ci        )
1005f9996aaSopenharmony_ci        parser.add_argument(
1015f9996aaSopenharmony_ci            "-cd",
1025f9996aaSopenharmony_ci            "--check_diffs",
1035f9996aaSopenharmony_ci            metavar="diffFilesPath",
1045f9996aaSopenharmony_ci            dest="diff_files_path",
1055f9996aaSopenharmony_ci            nargs=1,
1065f9996aaSopenharmony_ci            type=str,
1075f9996aaSopenharmony_ci            help="check all diff files as specific path.",
1085f9996aaSopenharmony_ci        )
1095f9996aaSopenharmony_ci        parser.add_argument(
1105f9996aaSopenharmony_ci            "-p",
1115f9996aaSopenharmony_ci            metavar="path",
1125f9996aaSopenharmony_ci            type=str,
1135f9996aaSopenharmony_ci            dest="path",
1145f9996aaSopenharmony_ci            help="check all files as specific path\
1155f9996aaSopenharmony_ci                            (the current directory by default).",
1165f9996aaSopenharmony_ci        )
1175f9996aaSopenharmony_ci        parser.add_argument(
1185f9996aaSopenharmony_ci            "-o",
1195f9996aaSopenharmony_ci            metavar="stdout/xls/json",
1205f9996aaSopenharmony_ci            nargs=1,
1215f9996aaSopenharmony_ci            dest="output_format",
1225f9996aaSopenharmony_ci            default="stdout",
1235f9996aaSopenharmony_ci            choices=["stdout", "xls", "json"],
1245f9996aaSopenharmony_ci            type=str,
1255f9996aaSopenharmony_ci            help="specific output format(stdout by default).",
1265f9996aaSopenharmony_ci        )
1275f9996aaSopenharmony_ci
1285f9996aaSopenharmony_ci    def store_args(self, args):
1295f9996aaSopenharmony_ci        if args.repo_pr is not None:
1305f9996aaSopenharmony_ci            self.repo_url = args.repo_pr[0]
1315f9996aaSopenharmony_ci            self.repo_num = args.repo_pr[1]
1325f9996aaSopenharmony_ci        self.diff_files_path = args.diff_files_path
1335f9996aaSopenharmony_ci        self.output_format = args.output_format
1345f9996aaSopenharmony_ci        if (args.path):
1355f9996aaSopenharmony_ci            self.check_path = os.path.normpath(args.path)
1365f9996aaSopenharmony_ci        self.white_dir_settings = args.white_dir_settings
1375f9996aaSopenharmony_ci
1385f9996aaSopenharmony_ci    def pre_check(self):
1395f9996aaSopenharmony_ci        if self.white_dir_settings == 'on':
1405f9996aaSopenharmony_ci            self.whitelist = self.handle_white_dir(self.check_path)
1415f9996aaSopenharmony_ci
1425f9996aaSopenharmony_ci    def start_check(self):
1435f9996aaSopenharmony_ci        print("---Start  check---\n")
1445f9996aaSopenharmony_ci        # check all gn
1455f9996aaSopenharmony_ci        gn_errs = CheckGn(self.ohos_root, black_dir=self.whitelist,
1465f9996aaSopenharmony_ci                          check_path=self.check_path).output()
1475f9996aaSopenharmony_ci
1485f9996aaSopenharmony_ci        # check all bundle.json
1495f9996aaSopenharmony_ci        bundle_errs = BundlesCheck.to_df(self.check_path)
1505f9996aaSopenharmony_ci
1515f9996aaSopenharmony_ci        if not os.path.exists("out"):
1525f9996aaSopenharmony_ci            os.mkdir("out")
1535f9996aaSopenharmony_ci        out_path = os.path.join(os.getcwd(), "out")
1545f9996aaSopenharmony_ci        table = PrettyTable(gn_errs.columns.to_list())
1555f9996aaSopenharmony_ci        table.add_rows(gn_errs.values.tolist())
1565f9996aaSopenharmony_ci        table_str = table.get_string()
1575f9996aaSopenharmony_ci        flags = os.O_WRONLY | os.O_CREAT
1585f9996aaSopenharmony_ci        modes = stat.S_IWUSR | stat.S_IRUSR
1595f9996aaSopenharmony_ci        with os.fdopen(
1605f9996aaSopenharmony_ci                os.open(os.path.join(out_path, "gn_problems.txt"), flags, modes), "w"
1615f9996aaSopenharmony_ci        ) as file:
1625f9996aaSopenharmony_ci            file.write(table_str)
1635f9996aaSopenharmony_ci
1645f9996aaSopenharmony_ci        # merge excel
1655f9996aaSopenharmony_ci        output_path = os.path.join(out_path, "output_errors.xlsx")
1665f9996aaSopenharmony_ci        with pd.ExcelWriter(output_path) as writer:
1675f9996aaSopenharmony_ci            bundle_errs.to_excel(writer, sheet_name="bundle_check", index=None)
1685f9996aaSopenharmony_ci            gn_errs.to_excel(writer, sheet_name="gn_check", index=None)
1695f9996aaSopenharmony_ci
1705f9996aaSopenharmony_ci        print("\nStatic check finish.\nPlease check: " + output_path)
1715f9996aaSopenharmony_ci        return
1725f9996aaSopenharmony_ci
1735f9996aaSopenharmony_ci    def check_end(self):
1745f9996aaSopenharmony_ci        print("\n---End check---")
1755f9996aaSopenharmony_ci        return
1765f9996aaSopenharmony_ci
1775f9996aaSopenharmony_ci
1785f9996aaSopenharmony_cidef main():
1795f9996aaSopenharmony_ci    csctglb = CsctGlobal()
1805f9996aaSopenharmony_ci    parser = argparse.ArgumentParser(
1815f9996aaSopenharmony_ci        description=f"Component Static Check Tool version {csctglb.version}",
1825f9996aaSopenharmony_ci    )
1835f9996aaSopenharmony_ci    csctglb.add_option(parser)
1845f9996aaSopenharmony_ci    args = parser.parse_args()
1855f9996aaSopenharmony_ci    csctglb.store_args(args)
1865f9996aaSopenharmony_ci    csctglb.pre_check()
1875f9996aaSopenharmony_ci    csctglb.start_check()
1885f9996aaSopenharmony_ci    csctglb.check_end()
1895f9996aaSopenharmony_ci    return 0
1905f9996aaSopenharmony_ci
1915f9996aaSopenharmony_ci
1925f9996aaSopenharmony_ciif __name__ == "__main__":
1935f9996aaSopenharmony_ci    sys.exit(main())
194