fritzkink
2023-12-25 92403c4d44b8479a50eb92bbf9311fa929ee3804
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))
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 + '.')
7e9f71 71                 self.name = data['name']
1e2fed 72                 self.supplied_packages = data['fmris']
AL 73                 self.required_packages = data['dependencies']
74
75     def required(self, component):
76         result = False
77
78         s1 = set(self.required_packages)
79         s2 = set(component.supplied_packages)
80         if s1.intersection(s2):
81             result = True
82
83         return result
84
85     def run_make(self, path, targets):
86
87         result = []
88
89         if self.debug:
90             logger.debug('Executing \'gmake %s\' in %s', targets, path)
91
92         proc = subprocess.Popen(['gmake', '-s', targets],
93                                 stdout=subprocess.PIPE,
94                                 stderr=subprocess.PIPE,
95                                 cwd=path,
96                                 universal_newlines=True)
97         stdout, stderr = proc.communicate()
98
99         for out in stdout.splitlines():
100             result.append(out.rstrip())
101
102         if self.debug:
103             if proc.returncode != 0:
104                 logger.debug('exit: %d, %s', proc.returncode, stderr)
105
106         return result
107
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)
112
113         return result
114