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]
21 # Copyright (c) 2010, Oracle and/or it's affiliates. All rights reserved.
25 # A simple program to enumerate components in the userland gate and report
26 # on dependency related information.
33 class Component(object):
34 def __init__(self
, path
=None, debug
=False):
38 self
.supplied_packages
= []
39 self
.required_packages
= []
41 component_pkg5_file
= os
.path
.join(self
.path
, 'pkg5')
42 if not os
.path
.isfile(component_pkg5_file
):
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
+ '.')
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()
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))
67 with
open(component_pkg5_file
, 'r') as f
:
68 data
= json
.loads(f
.read())
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
):
78 s1
= set(self
.required_packages
)
79 s2
= set(component
.supplied_packages
)
80 if s1
.intersection(s2
):
85 def run_make(self
, path
, targets
):
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
,
96 universal_newlines
=True)
97 stdout
, stderr
= proc
.communicate()
99 for out
in stdout
.splitlines():
100 result
.append(out
.rstrip())
103 if proc
.returncode
!= 0:
104 logger
.debug('exit: %d, %s', proc
.returncode
, stderr
)
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
)