python/tqdm: update to 4.67.1
[oi-userland.git] / tools / userland-mapping
blob5517893fc75e589af52a6171088dffbe8024fb92
1 #!/usr/bin/python3.9
4 # This file and its contents are supplied under the terms of the
5 # Common Development and Distribution License ("CDDL"), version 1.0.
6 # You may only use this file in accordance with the terms of version
7 # 1.0 of the CDDL.
9 # A full copy of the text of the CDDL should have accompanied this
10 # source.  A copy of the CDDL is also available via the Internet at
11 # http://www.illumos.org/license/CDDL.
15 # Copyright 2018 Adam Stevko
19 # mapping.py - generate mapping between component FMRI and component package names, to be used for different purposes,
20 # e.g. checking for outdated pacakges, vulnerable packages etc.
23 import argparse
24 import json
25 import os
26 import re
27 import logging
28 import subprocess
29 import multiprocessing
31 from bass.component import Component
33 try:
34     from scandir import walk
35 except ImportError:
36     from os import walk
38 logger = logging.getLogger('userland-mapping')
40 COMPONENT_MAPPING_FILENAME = 'mapping.json'
43 def find_component_paths(path, subdir='components', debug=False):
44     expression = re.compile(r'.+\.p5m$', re.IGNORECASE)
46     paths = []
47     workspace_path = os.path.join(path, subdir)
49     for dirpath, dirnames, filenames in walk(workspace_path):
50         for name in filenames:
51             if expression.match(name):
52                 if not os.path.isfile(os.path.join( dirpath, 'pkg5.ignore')):
53                     paths.append(dirpath)
54                 del dirnames[:]
55                 break
57     return paths
60 def generate_component_data(component_path, subdir='components'):
61     result = []
62     component = Component(path=component_path)
63     component_name = component.name
64     if not component_name:
65         raise ValueError('Component name is empty for path ' + component_path + '.')
66     component_fmris = component.supplied_packages
68     component_relative_path = component_path.split(os.path.join(os.environ['WS_TOP'], subdir))[-1].replace('/', '', 1)
70     return component_fmris, component_name, component_relative_path
73 def generate_userland_mapping(workspace_path, subdir='components', repo='userland', repo_map=[]):
74     mapping = []
76     paths = find_component_paths(path=workspace_path, subdir=subdir)
77     pool = multiprocessing.Pool(processes=multiprocessing.cpu_count())
78     results = pool.map(generate_component_data, paths)
80     for component_fmris, component_name, component_relative_path in results:
81         for component_fmri in component_fmris:
82             component_repo = repo
83             for rm in repo_map:
84                 if component_relative_path.startswith(rm['pfx']):
85                     component_repo = rm['repo']
87             mapping.append({'name': component_name,
88                             'fmri': component_fmri,
89                             'path': component_relative_path,
90                             'repo': component_repo})
92     component_mapping_file = os.path.join(workspace_path, subdir, COMPONENT_MAPPING_FILENAME)
93     with open(component_mapping_file, 'w') as f:
94         f.write(json.dumps(mapping, sort_keys=True, indent=4))
97 def main():
98     parser = argparse.ArgumentParser()
100     parser.add_argument('-w', '--workspace', default=os.getenv('WS_TOP'), help='Path to workspace')
101     parser.add_argument('--subdir', default='components', help='Directory holding components')
102     parser.add_argument('--repo', default='userland', help='Default target repository')
103     parser.add_argument('--repo-map', help='Target repository for this directory; e.g., encumbered/=userland-encumbered', action='append')
105     args = parser.parse_args()
107     workspace = args.workspace
108     subdir = args.subdir
110     repo = args.repo
111     repo_map = []
112     if args.repo_map:
113         for rm in args.repo_map:
114             l = rm.split("=")
115             if len(l) != 2:
116                 raise ValueError('invalid --repo-map: ' + rm)
117             repo_map.append({'pfx': l[0], 'repo': l[1]})
119     generate_userland_mapping(workspace_path=workspace, subdir=subdir, repo=repo, repo_map=repo_map)
121 if __name__ == '__main__':
122     main()