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.
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.
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]
22 # Copyright (c) 2010, Oracle and/or it's affiliates. All rights reserved.
26 # A simple program to enumerate components in the userland gate and report
27 # on dependency related information.
34 class Component(object):
35 def __init__(self
, path
=None, debug
=False):
39 self
.supplied_packages
= []
40 self
.required_packages
= []
42 component_pkg5_file
= os
.path
.join(self
.path
, 'pkg5')
43 if not os
.path
.isfile(component_pkg5_file
):
45 component_name
= self
.run_make(path
, 'print-value-COMPONENT_NAME')
46 if not component_name
:
47 raise ValueError('Component returns empty name at ' + self
.path
+ '.')
49 self
.name
= component_name
[0]
50 # get supplied packages, this may trigger the creation of a pkg5.fmris file
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()
59 self
.required_packages
= self
.run_make(path
, 'print-required-packages')
61 data
= { 'name' : self
.name
,
62 'fmris': self
.supplied_packages
,
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))
68 with
open(component_pkg5_file
, 'r') as f
:
69 data
= json
.loads(f
.read())
71 raise ValueError('Component pkg5 data is empty for path ' + self
.path
+ '.')
72 self
.name
= data
['name']
73 self
.supplied_packages
= data
['fmris']
74 self
.required_packages
= data
['dependencies']
76 def required(self
, component
):
79 s1
= set(self
.required_packages
)
80 s2
= set(component
.supplied_packages
)
81 if s1
.intersection(s2
):
86 def run_make(self
, path
, targets
):
91 logger
.debug('Executing \'gmake %s\' in %s', targets
, path
)
93 proc
= subprocess
.Popen(['gmake', '-s', targets
],
94 stdout
=subprocess
.PIPE
,
95 stderr
=subprocess
.PIPE
,
97 universal_newlines
=True)
98 stdout
, stderr
= proc
.communicate()
100 for out
in stdout
.splitlines():
101 result
.append(out
.rstrip())
104 if proc
.returncode
!= 0:
105 logger
.debug('exit: %d, %s', proc
.returncode
, stderr
)
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
)