xref: /aosp_15_r20/tools/asuite/aidegen/idea/xml_gen.py (revision c2e18aaa1096c836b086f94603d04f4eb9cf37f5)
1*c2e18aaaSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*c2e18aaaSAndroid Build Coastguard Worker#
3*c2e18aaaSAndroid Build Coastguard Worker# Copyright 2020 - The Android Open Source Project
4*c2e18aaaSAndroid Build Coastguard Worker#
5*c2e18aaaSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*c2e18aaaSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*c2e18aaaSAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*c2e18aaaSAndroid Build Coastguard Worker#
9*c2e18aaaSAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
10*c2e18aaaSAndroid Build Coastguard Worker#
11*c2e18aaaSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*c2e18aaaSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*c2e18aaaSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*c2e18aaaSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*c2e18aaaSAndroid Build Coastguard Worker# limitations under the License.
16*c2e18aaaSAndroid Build Coastguard Worker
17*c2e18aaaSAndroid Build Coastguard Worker"""Creates the xml files.
18*c2e18aaaSAndroid Build Coastguard Worker
19*c2e18aaaSAndroid Build Coastguard WorkerUsage example:
20*c2e18aaaSAndroid Build Coastguard Worker    vcs = XMLGenerator(module_path, 'vcs.xml')
21*c2e18aaaSAndroid Build Coastguard Worker    if not vcs.xml_obj:
22*c2e18aaaSAndroid Build Coastguard Worker        # Create the file directly.
23*c2e18aaaSAndroid Build Coastguard Worker        common_util.file_generate(vcs.xml_abspath, xml_content)
24*c2e18aaaSAndroid Build Coastguard Worker    else:
25*c2e18aaaSAndroid Build Coastguard Worker        # Add/remove elements to vcs.xml_obj by the methods of
26*c2e18aaaSAndroid Build Coastguard Worker        # ElementTree.Element object.
27*c2e18aaaSAndroid Build Coastguard Worker        vcs.xml_obj.append()
28*c2e18aaaSAndroid Build Coastguard Worker        vcs.xml_obj.makeelement()
29*c2e18aaaSAndroid Build Coastguard Worker        vcs.xml_obj.remove()
30*c2e18aaaSAndroid Build Coastguard Worker        # Update the XML content.
31*c2e18aaaSAndroid Build Coastguard Worker        vcs.create_xml()
32*c2e18aaaSAndroid Build Coastguard Worker"""
33*c2e18aaaSAndroid Build Coastguard Worker
34*c2e18aaaSAndroid Build Coastguard Workerfrom __future__ import absolute_import
35*c2e18aaaSAndroid Build Coastguard Worker
36*c2e18aaaSAndroid Build Coastguard Workerimport os
37*c2e18aaaSAndroid Build Coastguard Worker
38*c2e18aaaSAndroid Build Coastguard Workerfrom xml.etree import ElementTree
39*c2e18aaaSAndroid Build Coastguard Worker
40*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen import constant
41*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen import templates
42*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import aidegen_metrics
43*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import common_util
44*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import xml_util
45*c2e18aaaSAndroid Build Coastguard Worker
46*c2e18aaaSAndroid Build Coastguard Worker_GIT_PATH = '        <mapping directory="{GIT_DIR}" vcs="Git" />'
47*c2e18aaaSAndroid Build Coastguard Worker_IGNORE_PATH = '            <path value="{GIT_DIR}" />'
48*c2e18aaaSAndroid Build Coastguard Worker
49*c2e18aaaSAndroid Build Coastguard Worker
50*c2e18aaaSAndroid Build Coastguard Workerclass XMLGenerator:
51*c2e18aaaSAndroid Build Coastguard Worker    """Creates the xml file.
52*c2e18aaaSAndroid Build Coastguard Worker
53*c2e18aaaSAndroid Build Coastguard Worker    Attributes:
54*c2e18aaaSAndroid Build Coastguard Worker        _xml_abspath: A string of the XML's absolute path.
55*c2e18aaaSAndroid Build Coastguard Worker        _xml_obj: An ElementTree object.
56*c2e18aaaSAndroid Build Coastguard Worker    """
57*c2e18aaaSAndroid Build Coastguard Worker
58*c2e18aaaSAndroid Build Coastguard Worker    def __init__(self, module_abspath, xml_name):
59*c2e18aaaSAndroid Build Coastguard Worker        """Initializes XMLGenerator.
60*c2e18aaaSAndroid Build Coastguard Worker
61*c2e18aaaSAndroid Build Coastguard Worker        Args:
62*c2e18aaaSAndroid Build Coastguard Worker            module_abspath: A string of the module's absolute path.
63*c2e18aaaSAndroid Build Coastguard Worker            xml_name: A string of the xml file name.
64*c2e18aaaSAndroid Build Coastguard Worker        """
65*c2e18aaaSAndroid Build Coastguard Worker        self._xml_abspath = os.path.join(module_abspath, constant.IDEA_FOLDER,
66*c2e18aaaSAndroid Build Coastguard Worker                                         xml_name)
67*c2e18aaaSAndroid Build Coastguard Worker        self._xml_obj = None
68*c2e18aaaSAndroid Build Coastguard Worker        self.parse()
69*c2e18aaaSAndroid Build Coastguard Worker
70*c2e18aaaSAndroid Build Coastguard Worker    def parse(self):
71*c2e18aaaSAndroid Build Coastguard Worker        """Parses the XML file to an ElementTree object."""
72*c2e18aaaSAndroid Build Coastguard Worker        if os.path.exists(self._xml_abspath):
73*c2e18aaaSAndroid Build Coastguard Worker            self._xml_obj = xml_util.parse_xml(self._xml_abspath)
74*c2e18aaaSAndroid Build Coastguard Worker
75*c2e18aaaSAndroid Build Coastguard Worker    @property
76*c2e18aaaSAndroid Build Coastguard Worker    def xml_path(self):
77*c2e18aaaSAndroid Build Coastguard Worker        """Gets the xml absolute path."""
78*c2e18aaaSAndroid Build Coastguard Worker        return self._xml_abspath
79*c2e18aaaSAndroid Build Coastguard Worker
80*c2e18aaaSAndroid Build Coastguard Worker    @property
81*c2e18aaaSAndroid Build Coastguard Worker    def xml_obj(self):
82*c2e18aaaSAndroid Build Coastguard Worker        """Gets the xml object."""
83*c2e18aaaSAndroid Build Coastguard Worker        return self._xml_obj
84*c2e18aaaSAndroid Build Coastguard Worker
85*c2e18aaaSAndroid Build Coastguard Worker    def find_elements_by_name(self, element_type, name):
86*c2e18aaaSAndroid Build Coastguard Worker        """Finds the target elements by name attribute.
87*c2e18aaaSAndroid Build Coastguard Worker
88*c2e18aaaSAndroid Build Coastguard Worker        Args:
89*c2e18aaaSAndroid Build Coastguard Worker            element_type: A string of element's type.
90*c2e18aaaSAndroid Build Coastguard Worker            name: A string of element's name.
91*c2e18aaaSAndroid Build Coastguard Worker
92*c2e18aaaSAndroid Build Coastguard Worker        Return:
93*c2e18aaaSAndroid Build Coastguard Worker            List: ElementTree's element objects.
94*c2e18aaaSAndroid Build Coastguard Worker        """
95*c2e18aaaSAndroid Build Coastguard Worker        return [e for e in self._xml_obj.findall(element_type)
96*c2e18aaaSAndroid Build Coastguard Worker                if e.get('name') == name]
97*c2e18aaaSAndroid Build Coastguard Worker
98*c2e18aaaSAndroid Build Coastguard Worker    @staticmethod
99*c2e18aaaSAndroid Build Coastguard Worker    def append_node(parent, node_str):
100*c2e18aaaSAndroid Build Coastguard Worker        """Appends a node string under the parent element.
101*c2e18aaaSAndroid Build Coastguard Worker
102*c2e18aaaSAndroid Build Coastguard Worker        Args:
103*c2e18aaaSAndroid Build Coastguard Worker            parent: An element object, the new node's parent.
104*c2e18aaaSAndroid Build Coastguard Worker            node_str: A string, the new node's content.
105*c2e18aaaSAndroid Build Coastguard Worker        """
106*c2e18aaaSAndroid Build Coastguard Worker        try:
107*c2e18aaaSAndroid Build Coastguard Worker            parent.append(ElementTree.fromstring(node_str))
108*c2e18aaaSAndroid Build Coastguard Worker        except ElementTree.ParseError as xml_err:
109*c2e18aaaSAndroid Build Coastguard Worker            aidegen_metrics.send_exception_metrics(
110*c2e18aaaSAndroid Build Coastguard Worker                exit_code=constant.XML_PARSING_FAILURE, stack_trace=xml_err,
111*c2e18aaaSAndroid Build Coastguard Worker                log=node_str, err_msg='')
112*c2e18aaaSAndroid Build Coastguard Worker
113*c2e18aaaSAndroid Build Coastguard Worker    def create_xml(self):
114*c2e18aaaSAndroid Build Coastguard Worker        """Creates the xml file."""
115*c2e18aaaSAndroid Build Coastguard Worker        common_util.file_generate(self._xml_abspath, common_util.to_pretty_xml(
116*c2e18aaaSAndroid Build Coastguard Worker            self._xml_obj.getroot()))
117*c2e18aaaSAndroid Build Coastguard Worker
118*c2e18aaaSAndroid Build Coastguard Worker
119*c2e18aaaSAndroid Build Coastguard Workerdef gen_vcs_xml(module_path, git_paths):
120*c2e18aaaSAndroid Build Coastguard Worker    """Writes the git path into the .idea/vcs.xml.
121*c2e18aaaSAndroid Build Coastguard Worker
122*c2e18aaaSAndroid Build Coastguard Worker    For main module, the vcs.xml should include all modules' git path.
123*c2e18aaaSAndroid Build Coastguard Worker    For the whole AOSP case, ignore creating the vcs.xml. Instead, add the
124*c2e18aaaSAndroid Build Coastguard Worker    ignored Git paths in the workspace.xml.
125*c2e18aaaSAndroid Build Coastguard Worker
126*c2e18aaaSAndroid Build Coastguard Worker    Args:
127*c2e18aaaSAndroid Build Coastguard Worker        module_path: A string, the absolute path of the module.
128*c2e18aaaSAndroid Build Coastguard Worker        git_paths: A list of git paths.
129*c2e18aaaSAndroid Build Coastguard Worker    """
130*c2e18aaaSAndroid Build Coastguard Worker    git_mappings = [_GIT_PATH.format(GIT_DIR=p) for p in git_paths if p]
131*c2e18aaaSAndroid Build Coastguard Worker    vcs = XMLGenerator(module_path, 'vcs.xml')
132*c2e18aaaSAndroid Build Coastguard Worker    if module_path != common_util.get_android_root_dir() or not vcs.xml_obj:
133*c2e18aaaSAndroid Build Coastguard Worker        common_util.file_generate(vcs.xml_path, templates.XML_VCS.format(
134*c2e18aaaSAndroid Build Coastguard Worker            GIT_MAPPINGS='\n'.join(git_mappings)))
135*c2e18aaaSAndroid Build Coastguard Worker
136*c2e18aaaSAndroid Build Coastguard Worker
137*c2e18aaaSAndroid Build Coastguard Workerdef write_ignore_git_dirs_file(module_path, ignore_paths):
138*c2e18aaaSAndroid Build Coastguard Worker    """Write the ignored git paths in the .idea/workspace.xml.
139*c2e18aaaSAndroid Build Coastguard Worker
140*c2e18aaaSAndroid Build Coastguard Worker    Args:
141*c2e18aaaSAndroid Build Coastguard Worker        module_path: A string, the absolute path of the module.
142*c2e18aaaSAndroid Build Coastguard Worker        ignore_paths: A list of git paths.
143*c2e18aaaSAndroid Build Coastguard Worker    """
144*c2e18aaaSAndroid Build Coastguard Worker    ignores = [_IGNORE_PATH.format(GIT_DIR=p) for p in ignore_paths]
145*c2e18aaaSAndroid Build Coastguard Worker    workspace = XMLGenerator(module_path, 'workspace.xml')
146*c2e18aaaSAndroid Build Coastguard Worker    if not workspace.xml_obj:
147*c2e18aaaSAndroid Build Coastguard Worker        common_util.file_generate(workspace.xml_path,
148*c2e18aaaSAndroid Build Coastguard Worker                                  templates.XML_WORKSPACE.format(
149*c2e18aaaSAndroid Build Coastguard Worker                                      GITS=''.join(ignores)))
150*c2e18aaaSAndroid Build Coastguard Worker        return
151*c2e18aaaSAndroid Build Coastguard Worker    for conf in workspace.find_elements_by_name('component',
152*c2e18aaaSAndroid Build Coastguard Worker                                                'VcsManagerConfiguration'):
153*c2e18aaaSAndroid Build Coastguard Worker        workspace.xml_obj.getroot().remove(conf)
154*c2e18aaaSAndroid Build Coastguard Worker    workspace.append_node(workspace.xml_obj.getroot(),
155*c2e18aaaSAndroid Build Coastguard Worker                          templates.IGNORED_GITS.format(GITS=''.join(ignores)))
156*c2e18aaaSAndroid Build Coastguard Worker    workspace.create_xml()
157