blob: 29147e71bea8a5b4f893ba8567baf0724a52de51 [file] [log] [blame]
Aaron Masseye4d92222020-07-13 17:41:29 +00001#!/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
9import xml.parsers.expat as xml
10import sys
11import argparse
12import pathlib
13
14def 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 Masseye4d92222020-07-13 17:41:29 +000039 project_name = attrs['name']
Aaron Massey0a509122020-08-10 21:46:43 +000040 project_path = attrs.get('path', project_name)
41 dest_branch = attrs.get('dest-branch')
Aaron Masseye4d92222020-07-13 17:41:29 +000042 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
60def 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
77if __name__ == '__main__':
78 sys.exit(main(sys.argv[1:]))