commit | author | age
|
de89cf
|
1 |
#!/usr/bin/python3.9 |
404117
|
2 |
|
AŠ |
3 |
# |
|
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. |
|
8 |
# |
|
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. |
|
12 |
# |
|
13 |
|
|
14 |
# |
|
15 |
# Copyright 2018 Adam Stevko |
|
16 |
# |
|
17 |
|
|
18 |
# |
|
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. |
|
21 |
# |
|
22 |
|
|
23 |
import argparse |
|
24 |
import json |
|
25 |
import os |
|
26 |
import re |
|
27 |
import logging |
|
28 |
import subprocess |
|
29 |
import multiprocessing |
|
30 |
|
7e9f71
|
31 |
from bass.component import Component |
1e2fed
|
32 |
|
404117
|
33 |
try: |
AŠ |
34 |
from scandir import walk |
|
35 |
except ImportError: |
|
36 |
from os import walk |
|
37 |
|
|
38 |
logger = logging.getLogger('userland-mapping') |
|
39 |
|
1e2fed
|
40 |
COMPONENT_MAPPING_FILENAME = 'mapping.json' |
404117
|
41 |
|
AŠ |
42 |
|
|
43 |
def find_component_paths(path, subdir='components', debug=False): |
|
44 |
expression = re.compile(r'.+\.p5m$', re.IGNORECASE) |
|
45 |
|
|
46 |
paths = [] |
|
47 |
workspace_path = os.path.join(path, subdir) |
|
48 |
|
|
49 |
for dirpath, dirnames, filenames in walk(workspace_path): |
|
50 |
for name in filenames: |
|
51 |
if expression.match(name): |
9cb600
|
52 |
if not os.path.isfile(os.path.join( dirpath, 'pkg5.ignore')): |
AL |
53 |
paths.append(dirpath) |
404117
|
54 |
del dirnames[:] |
AŠ |
55 |
break |
|
56 |
|
|
57 |
return paths |
|
58 |
|
|
59 |
|
11232f
|
60 |
def generate_component_data(component_path, subdir='components'): |
404117
|
61 |
result = [] |
7e9f71
|
62 |
component = Component(path=component_path) |
AL |
63 |
component_name = component.name |
1e2fed
|
64 |
if not component_name: |
AL |
65 |
raise ValueError('Component name is empty for path ' + component_path + '.') |
|
66 |
component_fmris = component.supplied_packages |
404117
|
67 |
|
11232f
|
68 |
component_relative_path = component_path.split(os.path.join(os.environ['WS_TOP'], subdir))[-1].replace('/', '', 1) |
404117
|
69 |
|
AŠ |
70 |
return component_fmris, component_name, component_relative_path |
|
71 |
|
|
72 |
|
780de6
|
73 |
def generate_userland_mapping(workspace_path, subdir='components', repo='userland', repo_map=[]): |
404117
|
74 |
mapping = [] |
AŠ |
75 |
|
|
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) |
|
79 |
|
|
80 |
for component_fmris, component_name, component_relative_path in results: |
|
81 |
for component_fmri in component_fmris: |
780de6
|
82 |
component_repo = repo |
JMC |
83 |
for rm in repo_map: |
|
84 |
if component_relative_path.startswith(rm['pfx']): |
|
85 |
component_repo = rm['repo'] |
|
86 |
|
1e2fed
|
87 |
mapping.append({'name': component_name, |
AL |
88 |
'fmri': component_fmri, |
780de6
|
89 |
'path': component_relative_path, |
JMC |
90 |
'repo': component_repo}) |
404117
|
91 |
|
1e2fed
|
92 |
component_mapping_file = os.path.join(workspace_path, subdir, COMPONENT_MAPPING_FILENAME) |
404117
|
93 |
with open(component_mapping_file, 'w') as f: |
AŠ |
94 |
f.write(json.dumps(mapping, sort_keys=True, indent=4)) |
|
95 |
|
|
96 |
|
|
97 |
def main(): |
|
98 |
parser = argparse.ArgumentParser() |
|
99 |
|
|
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') |
780de6
|
102 |
parser.add_argument('--repo', default='userland', help='Default target repository') |
JMC |
103 |
parser.add_argument('--repo-map', help='Target repository for this directory; e.g., encumbered/=userland-encumbered', action='append') |
404117
|
104 |
|
AŠ |
105 |
args = parser.parse_args() |
|
106 |
|
|
107 |
workspace = args.workspace |
|
108 |
subdir = args.subdir |
|
109 |
|
780de6
|
110 |
repo = args.repo |
JMC |
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]}) |
|
118 |
|
|
119 |
generate_userland_mapping(workspace_path=workspace, subdir=subdir, repo=repo, repo_map=repo_map) |
404117
|
120 |
|
AŠ |
121 |
if __name__ == '__main__': |
|
122 |
main() |