makemaker-defaults.mk: fallback COMPONENT_PROJECT_URL to dist
[oi-userland.git] / tools / bass / component.py
blob663d79f6d80032b87759ee5987008b394fc03e0d
2 # CDDL HEADER START
4 # The contents of this file are subject to the terms of the
5 # Common Development and Distribution License (the "License").
6 # You may not use this file except in compliance with the License.
8 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 # or http://www.opensolaris.org/os/licensing.
10 # See the License for the specific language governing permissions
11 # and limitations under the License.
13 # When distributing Covered Code, include this CDDL HEADER in each
14 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 # If applicable, add the following below this CDDL HEADER, with the
16 # fields enclosed by brackets "[]" replaced with your own identifying
17 # information: Portions Copyright [yyyy] [name of copyright owner]
19 # CDDL HEADER END
21 # Copyright (c) 2010, Oracle and/or it's affiliates. All rights reserved.
24 # bass-o-matic.py
25 # A simple program to enumerate components in the userland gate and report
26 # on dependency related information.
29 import os
30 import subprocess
31 import json
33 class Component(object):
34 def __init__(self, path=None, debug=False):
35 self.debug = debug
36 self.path = path
37 self.name = None
38 self.supplied_packages = []
39 self.required_packages = []
40 if path:
41 component_pkg5_file = os.path.join(self.path, 'pkg5')
42 if not os.path.isfile(component_pkg5_file):
43 # get component name
44 component_name = self.run_make(path, 'print-value-COMPONENT_NAME')
45 if not component_name:
46 raise ValueError('Component returns empty name at ' + self.path + '.')
47 else:
48 self.name = component_name[0]
49 # get supplied packages, this may trigger the creation of a pkg5.fmris file
50 self.supplied_packages = self.run_make(path, 'print-package-names')
51 # always update fmris if list is overriden
52 component_pkg5_fmris_file = os.path.join(self.path, 'pkg5.fmris')
53 if os.path.isfile(component_pkg5_fmris_file):
54 with open(component_pkg5_fmris_file, 'r') as f:
55 self.supplied_packages = f.read().splitlines()
57 # get dependencies
58 self.required_packages = self.run_make(path, 'print-required-packages')
60 data = { 'name' : self.name,
61 'fmris': self.supplied_packages,
62 'dependencies' : self.required_packages }
63 with open(component_pkg5_file, 'w') as f:
64 f.write(json.dumps(data, sort_keys=True, indent=4))
65 f.write('\n')
66 else:
67 with open(component_pkg5_file, 'r') as f:
68 data = json.loads(f.read())
69 if not data:
70 raise ValueError('Component pkg5 data is empty for path ' + self.path + '.')
71 self.name = data['name']
72 self.supplied_packages = data['fmris']
73 self.required_packages = data['dependencies']
75 def required(self, component):
76 result = False
78 s1 = set(self.required_packages)
79 s2 = set(component.supplied_packages)
80 if s1.intersection(s2):
81 result = True
83 return result
85 def run_make(self, path, targets):
87 result = []
89 if self.debug:
90 logger.debug('Executing \'gmake %s\' in %s', targets, path)
92 proc = subprocess.Popen(['gmake', '-s', '--no-print-directory', targets],
93 stdout=subprocess.PIPE,
94 stderr=subprocess.PIPE,
95 cwd=path,
96 universal_newlines=True)
97 stdout, stderr = proc.communicate()
99 for out in stdout.splitlines():
100 result.append(out.rstrip())
102 if self.debug:
103 if proc.returncode != 0:
104 logger.debug('exit: %d, %s', proc.returncode, stderr)
106 return result
108 def __str__(self):
109 result = 'Component:\n\tPath: %s\n' % self.path
110 result += '\tProvides Package(s):\n\t\t%s\n' % '\t\t'.join(self.supplied_packages)
111 result += '\tRequired Package(s):\n\t\t%s\n' % '\t\t'.join(self.required_packages)
113 return result