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