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