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