Marcel Telka
2024-04-08 27ea4582c008083fc42d6e52da1dc3f6ff5cd25e
commit | author | age
705e8c 1 #!/usr/bin/python2.7
2
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 # userland-bump - bump component revision to trigger rebuild or bump component version
20 #
21
22 from __future__ import print_function
23
24 import argparse
25 import subprocess
26 import os
27 import re
28 import sys
29 import json
30
31
32 def load_db(file_name):
33     with open(file_name, 'r') as f:
34         return json.loads(f.read())
35
36
37 def convert_fmri_to_path(fmri):
38
39     result = None
40
41     ws_tools = os.path.dirname(os.path.realpath(sys.argv[0]))
42     component_translate = os.path.join(ws_tools, 'component-translate')
43
44     args = [component_translate, '--fmri', fmri]
45     proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
46     for out in proc.stdout:
47         result = out.rstrip()
48
49     return result
50
51
52 def locate_dependents(path, data):
53     result = []
54
55     for component in data.keys():
56         if path in data[component]:
57             result.append(component)
58
59     return result
60
61
62 def bump_component_revision(contents):
63     contents_new = []
64
65     component_version_idx = 0
66     component_revision_idx = 0
67     has_component_revision = False
68     for idx, line in enumerate(contents):
69         if re.match('^COMPONENT_VERSION=', line):
70             component_version_idx = idx
71
72         if re.match('^COMPONENT_REVISION', line):
73             has_component_revision = True
74             component_revision_idx = idx
75
76     if has_component_revision:
77         contents_new.extend(contents[:component_revision_idx])
78
79         component_revision = contents[component_revision_idx].split('=')[-1]
80         try:
81             component_revision_int = int(component_revision)
82         except ValueError:
83             print('\tSkipping component, COMPONENT_REVISION field malformed: {}'.format(component_revision))
84             return contents
85         else:
86             component_revision_int += 1
87             contents_new.append('COMPONENT_REVISION=\t{}\n'.format(component_revision_int))
88
89         contents_new.extend(contents[component_revision_idx + 1:])
90     else:
91         contents_new.extend(contents[:component_version_idx + 1])
92         contents_new.append('COMPONENT_REVISION=\t1\n')
93         contents_new.extend(contents[component_version_idx + 1:])
94
95     return contents_new
96
97
98 def rebuild_dependent_fmris(fmri, db_path=None, workspace=None, subdir='components', verbose=False, dry_run=False):
99     data = load_db(db_path)
100
101     path = convert_fmri_to_path(fmri)
102     dependent_paths = locate_dependents(path=path, data=data)
103     if not dry_run:
104         for component_path in dependent_paths:
105             if verbose:
106                 print('Processing {}'.format(component_path))
107     
108             contents = []
109             makefile = os.path.join(workspace, subdir, component_path, 'Makefile')
110             with open(makefile, 'r') as f:
111                 contents = f.readlines()
112     
113             contents = bump_component_revision(contents)
114     
115             with open(makefile, 'w') as f:
116                 for line in contents:
117                     f.write(line)
118     else:
119         for component_path in dependent_paths:
120             print('{0}'.format(component_path))
121
122
123 def main():
124     db_default_path = os.path.join(os.path.dirname(sys.argv[0]).rsplit('/', 1)[0], 'components', 'dependencies.json')
125     workspace_default_path = os.path.dirname(os.path.dirname(sys.argv[0]))
126
127     parser = argparse.ArgumentParser()
128     parser.add_argument('--db-path', default=db_default_path, help=argparse.SUPPRESS)
129     parser.add_argument('-w', '--workspace', default=workspace_default_path, help='Path to workspace')
130     parser.add_argument('--subdir', default='components', help='Directory holding components')
131     parser.add_argument('--rebuild-dependents', action='store_true', default=False,
132                         help='Bump COMPONENT_REVISION of dependent components')
133     parser.add_argument('-n', '--dry-run', action='store_true', default=False,
134                         help='Do not execute, only print the list of resolved components')
135     parser.add_argument('--fmri', required=True, help='Component FMRI')
136     parser.add_argument('-v', '--verbose', action='store_true', default=False, help='Verbose output')
137     args = parser.parse_args()
138
139     db_path = args.db_path
140     rebuild_dependents = args.rebuild_dependents
141     dry_run = args.dry_run
142     fmri = args.fmri
143     verbose = args.verbose
144     workspace = args.workspace
145     subdir = args.subdir
146
147     if rebuild_dependents:
148         rebuild_dependent_fmris(fmri=fmri, db_path=db_path, workspace=workspace, subdir=subdir, verbose=verbose, dry_run=dry_run)
149
150
151 if __name__ == '__main__':
152     main()