diff options
Diffstat (limited to 'llvm_tools/manifest_utils.py')
-rw-r--r-- | llvm_tools/manifest_utils.py | 71 |
1 files changed, 56 insertions, 15 deletions
diff --git a/llvm_tools/manifest_utils.py b/llvm_tools/manifest_utils.py index 3d6337bf..e53afa6d 100644 --- a/llvm_tools/manifest_utils.py +++ b/llvm_tools/manifest_utils.py @@ -11,7 +11,7 @@ on toolchain projects (llvm-project, etc.) which are public. from pathlib import Path import shutil import subprocess -from typing import List, Union +from typing import List, Optional, Union from xml.etree import ElementTree import atomic_write_file @@ -28,13 +28,64 @@ class UpdateManifestError(Exception): """Error occurred when updating the manifest.""" -def make_xmlparser(): +class ManifestParseError(Exception): + """Error occurred when parsing the contents of the manifest.""" + + +def make_xmlparser() -> ElementTree.XMLParser: """Return a new xmlparser with custom TreeBuilder.""" return ElementTree.XMLParser( target=ElementTree.TreeBuilder(insert_comments=True) ) +def _find_llvm_project_in_manifest_tree( + xmlroot: ElementTree.Element, +) -> Optional[ElementTree.Element]: + """Returns the llvm-project `project` in `xmlroot`, if it exists.""" + for child in xmlroot: + if ( + child.tag == "project" + and child.attrib.get("path") == LLVM_PROJECT_PATH + ): + return child + return None + + +def extract_current_llvm_hash(src_tree: Path) -> str: + """Returns the current LLVM SHA for the CrOS tree rooted at `src_tree`. + + Raises: + ManifestParseError if the manifest didn't have the expected contents. + """ + xmlroot = ElementTree.parse( + get_chromeos_manifest_path(src_tree), parser=make_xmlparser() + ).getroot() + return extract_current_llvm_hash_from_xml(xmlroot) + + +def extract_current_llvm_hash_from_xml(xmlroot: ElementTree.Element) -> str: + """Returns the current LLVM SHA for the parsed XML file. + + Raises: + ManifestParseError if the manifest didn't have the expected contents. + """ + if xmlroot.tag != "manifest": + raise ManifestParseError( + f"Root tag is {xmlroot.tag}; should be `manifest`." + ) + + llvm_project = _find_llvm_project_in_manifest_tree(xmlroot) + if llvm_project is None: + raise ManifestParseError("No llvm-project `project` found in manifest.") + + revision = llvm_project.attrib.get("revision") + if not revision: + raise ManifestParseError("Toolchain's `project` has no revision.") + + return revision + + def update_chromeos_manifest(revision: str, src_tree: Path) -> Path: """Replaces the manifest project revision with 'revision'. @@ -73,21 +124,11 @@ def get_chromeos_manifest_path(src_tree: Path) -> Path: def update_chromeos_manifest_tree(revision: str, xmlroot: ElementTree.Element): """Update the revision info for LLVM for a manifest XML root.""" - - # This exists mostly for testing. - def is_llvm_project(child): - return ( - child.tag == "project" and child.attrib["path"] == LLVM_PROJECT_PATH - ) - - finder = (child for child in xmlroot if is_llvm_project(child)) - llvm_project_elem = next(finder, None) + llvm_project_elem = _find_llvm_project_in_manifest_tree(xmlroot) # Element objects can be falsy, so we need to explicitly check None. - if llvm_project_elem is not None: - # Update the llvm revision git sha - llvm_project_elem.attrib["revision"] = revision - else: + if llvm_project_elem is None: raise UpdateManifestError("xmltree did not have llvm-project") + llvm_project_elem.attrib["revision"] = revision def format_manifest(repo_manifest: Path): |