Aaron Massey | e4d9222 | 2020-07-13 17:41:29 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # -*- coding: utf-8 -*- |
| 3 | # Copyright 2020 The Chromium OS Authors. All rights reserved. |
| 4 | # Use of this source code is governed by a BSD-style license that can be |
| 5 | # found in the LICENSE file. |
| 6 | |
| 7 | """This is a utility script for parsing repo manifest files used by gerrit.el""" |
| 8 | |
| 9 | import xml.parsers.expat as xml |
| 10 | import sys |
| 11 | import argparse |
| 12 | import pathlib |
| 13 | |
| 14 | def parse_manifest_projects_to_lisp_alist(manifest_path): |
| 15 | """Parse manifest xml to Lisp alist. |
| 16 | |
| 17 | Any project without a dest-branch attribute is skipped. |
| 18 | |
| 19 | Args: |
| 20 | manifest_path: The path to a trusted repo manifest file to parse project elements. |
| 21 | |
| 22 | Returns: |
| 23 | Lisp readable alist with elements of the form ((name . dest-branch) . path) |
| 24 | |
| 25 | Raises: |
| 26 | ExpatError: An error occured when attempting to parse. |
| 27 | """ |
| 28 | |
| 29 | assoc_list_entries = [] |
| 30 | |
| 31 | def _project_elem_handler(name, attrs): |
| 32 | """XML element handler collecting project elements to form a Lisp alist. |
| 33 | |
| 34 | Args: |
| 35 | name: The name of the handled xml element. |
| 36 | attrs: A dictionary of the handled xml element's attributes. |
| 37 | """ |
| 38 | if name == 'project': |
Aaron Massey | e4d9222 | 2020-07-13 17:41:29 +0000 | [diff] [blame] | 39 | project_name = attrs['name'] |
Aaron Massey | 0a50912 | 2020-08-10 21:46:43 +0000 | [diff] [blame^] | 40 | project_path = attrs.get('path', project_name) |
| 41 | dest_branch = attrs.get('dest-branch') |
Aaron Massey | e4d9222 | 2020-07-13 17:41:29 +0000 | [diff] [blame] | 42 | if not dest_branch: |
| 43 | # We skip anything without a dest-branch |
| 44 | return |
| 45 | # We don't want the refs/heads/ prefix of dest-branch |
| 46 | dest_branch = dest_branch.replace('refs/heads/', '') |
| 47 | |
| 48 | key = '("{}" . "{}")'.format(project_name, dest_branch) |
| 49 | value = '"{}"'.format(project_path) |
| 50 | |
| 51 | assoc_list_entries.append('({} . {})'.format(key, value)) |
| 52 | |
| 53 | p = xml.ParserCreate() |
| 54 | p.StartElementHandler = _project_elem_handler |
| 55 | with open(manifest_path, 'rb') as manifest_fd: |
| 56 | p.ParseFile(manifest_fd) |
| 57 | return '({})'.format(''.join(assoc_list_entries)) |
| 58 | |
| 59 | |
| 60 | def main(argv): |
| 61 | """main.""" |
| 62 | arg_parser = argparse.ArgumentParser() |
| 63 | arg_parser.add_argument('repo_manifest_path', |
| 64 | type=pathlib.Path, |
| 65 | help='System path to repo manifest xml file.') |
| 66 | args = arg_parser.parse_args(argv) |
| 67 | |
| 68 | try: |
| 69 | print(parse_manifest_projects_to_lisp_alist(args.repo_manifest_path)) |
| 70 | return 0 |
| 71 | |
| 72 | except xml.ExpatError as err: |
| 73 | print('XML Parsing Error:', err) |
| 74 | return 1 |
| 75 | |
| 76 | |
| 77 | if __name__ == '__main__': |
| 78 | sys.exit(main(sys.argv[1:])) |