|
1 #!/usr/bin/python2.6 |
|
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 |
|
33 import subprocess |
|
34 |
|
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 |
|
126 make_arg=None |
|
127 component_arg=None |
|
128 template_zone=None |
|
129 workspace = os.getenv('WS_TOP') |
|
130 |
|
131 try: |
|
132 opts, args = getopt.getopt(sys.argv[1:], "w:c:d", |
|
133 [ "debug", "workspace=", "components=", |
|
134 "make", "component=", "template-zone=" ]) |
|
135 except getopt.GetoptError, err: |
|
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 |
|
144 elif opt in [ "--make" ]: |
|
145 make_arg = True |
|
146 elif opt in [ "--component" ]: |
|
147 component_arg = arg |
|
148 elif opt in [ "--template-zone" ]: |
|
149 template_zone = arg |
|
150 elif opt in [ "-d", "--debug" ]: |
|
151 debug = sys.stdout |
|
152 else: |
|
153 assert False, "unknown option" |
|
154 |
|
155 component_paths = FindComponentPaths(workspace, debug) |
|
156 |
|
157 if make_arg: |
|
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 |
|
164 if components_arg: |
|
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() |