#!/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()