Norm Jacobs
2010-09-19 79b849686f586ef87a8a89413e6cc7ba36b7ea9a
commit | author | age
a325d4 1 #!/usr/bin/python2.6
NJ 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 sys
32 import re
79b849 33 import subprocess
a325d4 34
NJ 35 # Locate SCM directories containing Userland components by searching from
36 # from a supplied top of tree for .p5m files.  Once a .p5m file is located,
37 # that directory is added to the list and no children are searched.
38 def FindComponentPaths(path, debug=None):
39     expression = re.compile(".+\.p5m$", re.IGNORECASE)
40
41     paths = []
42
43     if debug:
44         print >>debug, "searching %s for component directories" % path
45
46     for dirpath, dirnames, filenames in os.walk(path + '/components'):
47         found = 0
48
49         for name in filenames:
50             if expression.match(name):
51                 if debug:
52                     print >>debug, "found %s" % dirpath
53                 paths.append(dirpath)
54                 del dirnames[:]
55                 break
56
57     return sorted(paths)
58
59 class BassComponent:
60     def __init__(self, path=None, debug=None):
61         self.debug = debug
62         self.path = path
63         if path:
64             # get supplied packages    (cd path ; gmake print-package-names)
65             self.supplied_packages = self.run_make(path, 'print-package-names')
66
67             # get supplied paths    (cd path ; gmake print-package-paths)
68             self.supplied_paths = self.run_make(path, 'print-package-paths')
69
70             # get required paths    (cd path ; gmake print-required-paths)
71             self.required_paths = self.run_make(path, 'print-required-paths')
72
73     def required(self, component):
74         result = False
75
76         s1 = set(self.required_paths)
77         s2 = set(component.supplied_paths)
78         if s1.intersection(s2):
79             result = True
80
81         return result
82
83     def run_make(self, path, targets):
84
85         result = list()
86
87         if self.debug:
88             print >>self.debug, "Executing 'gmake %s' in %s" % (targets, path)
89
90         proc = subprocess.Popen(['gmake', targets], cwd=path,
91                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
92         p = proc.stdout
93
94         for out in p:
95             result.append(out)
96
97         if self.debug:
98             proc.wait()
99             if proc.returncode != 0:
100                 print >>self.debug, "exit: %d, %s" % (proc.returncode, proc.stderr.read())
101     
102         return result
103
104     def __str__(self):
105         result = "Component:\n\tPath: %s\n" % self.path
106         result = result + "\tProvides Package(s):\n\t\t%s\n" % '\t\t'.join(self.supplied_packages)
107         result = result + "\tProvides Path(s):\n\t\t%s\n" % '\t\t'.join(self.supplied_paths)
108         result = result + "\tRequired Path(s):\n\t\t%s\n" % '\t\t'.join(self.required_paths)
109
110         return result
111
112 def usage():
113     print "Usage: %s [-c|--components=(path|depend)] [-z|--zone (zone)]" % (sys.argv[0].split('/')[-1])
114     sys.exit(1)
115
116 def main():
117     import getopt
118     import sys
119
120     # FLUSH STDOUT 
121     sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
122
123     components = {}
124     debug=None
125     components_arg=None
79b849 126     make_arg=None
NJ 127     component_arg=None
128     template_zone=None
a325d4 129     workspace = os.getenv('WS_TOP')
NJ 130
131     try:
132         opts, args = getopt.getopt(sys.argv[1:], "w:c:d",
79b849 133             [ "debug", "workspace=", "components=",
NJ 134               "make", "component=", "template-zone=" ])
a325d4 135     except getopt.GetoptError, err:
NJ 136         print str(err)
137         usage()
138
139     for opt, arg in opts:
140         if opt in [ "-w", "--workspace" ]:
141             workspace = arg
142         elif opt in [ "-l", "--components" ]:
143             components_arg = arg
79b849 144         elif opt in [ "--make" ]:
NJ 145             make_arg = True
146         elif opt in [ "--component" ]:
147             component_arg = arg
148         elif opt in [ "--template-zone" ]:
149             template_zone = arg
a325d4 150         elif opt in [ "-d", "--debug" ]:
NJ 151             debug = sys.stdout
152         else:
153             assert False, "unknown option"
154
155     component_paths = FindComponentPaths(workspace, debug)
156
79b849 157     if make_arg:
NJ 158         if template_zone:
159             print "using template zone %s to create a build environment for %s to run '%s'" % (template_zone, component_arg, ['gmake'] + args)
160         proc = subprocess.Popen(['gmake'] + args)
161     proc.wait()
162         sys.exit(0)
163
a325d4 164     if components_arg:
NJ 165         if components_arg in [ 'path', 'paths', 'dir', 'dirs', 'directories' ]:
166             for path in component_paths:
167                 print "%s" % path
168             
169         elif components_arg in [ 'depend', 'dependencies' ]:
170             for path in component_paths:
171                 components[path] = BassComponent(path, debug)
172
173             for c_path in components.keys():
174                 component = components[c_path]
175
176                 for d_path in components.keys():
177                     if (c_path != d_path and
178                         component.required(components[d_path])):
179                           print "%s: %s" % (c_path, d_path)
180
181         sys.exit(0)
182
183     sys.exit(1)
184
185 if __name__ == "__main__":
186     main()