|
1 #!/usr/bin/python |
|
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) 2012, Oracle and/or it's affiliates. All rights reserved. |
|
23 # |
|
24 # |
|
25 # gen_components |
|
26 # A simple script to generate (on stdout), the component.html web page |
|
27 # found at: http://userland.us.oracle.com/components.html |
|
28 # |
|
29 |
|
30 import getopt |
|
31 import os |
|
32 import sys |
|
33 |
|
34 debug = False |
|
35 |
|
36 # Hashtable of components with TPNOs keyed by component name. |
|
37 comp_TPNOs = {} |
|
38 |
|
39 # Hashtable of RE's, RM's and Teams keyed by component path. |
|
40 owners = {} |
|
41 |
|
42 # Initial HTML for the generated web page. |
|
43 preamble = """ |
|
44 <html> |
|
45 <head> |
|
46 <style type='text/css' media='screen'> |
|
47 @import '/css/demo_table.css'; |
|
48 @import '/css/ColVis.css'; |
|
49 @import '/css/ColReorder.css'; |
|
50 |
|
51 tr.even:hover, tr.even:hover td.sorting_1 , |
|
52 tr.odd:hover, tr.odd:hover td.sorting_1 { |
|
53 background-color: gold; |
|
54 } |
|
55 |
|
56 </style> |
|
57 <script type='text/javascript' src='js/jquery.js'></script> |
|
58 <script type='text/javascript' src='js/jquery.dataTables.js'></script> |
|
59 <script type='text/javascript' src='js/ColReorder.js'></script> |
|
60 <script type='text/javascript' src='js/ColVis.js'></script> |
|
61 |
|
62 <script> |
|
63 $(document).ready(function() { |
|
64 $('#components').dataTable({ |
|
65 "sDom": 'C<"clear">Rlfrtip', |
|
66 bPaginate: true, |
|
67 bFilter: true, |
|
68 bSort: true, |
|
69 iDisplayLength: -1, |
|
70 aLengthMenu: [ [ 10, 50, -1], [ 10, 50, 'All'] ] |
|
71 }); |
|
72 }); |
|
73 </script> |
|
74 </head> |
|
75 <body> |
|
76 |
|
77 <h1>Userland Components</h1> |
|
78 <p> |
|
79 <table align='center' id='components'> |
|
80 <thead> |
|
81 <tr> |
|
82 <th>Component</th> |
|
83 <th>Version</th> |
|
84 <th>Gate Path</th> |
|
85 <th>Package(s)</th> |
|
86 <th>ARC Case(s)</th> |
|
87 <th>License(s)</th> |
|
88 <th>TPNO</th> |
|
89 <th>BugDB</th> |
|
90 <th>RE</th> |
|
91 <th>RM</th> |
|
92 <th>Team</th> |
|
93 </tr> |
|
94 </thead> |
|
95 <tbody> |
|
96 """ |
|
97 |
|
98 # Final HTML for the generated web page. |
|
99 postamble = """ |
|
100 </tr> |
|
101 </tbody> |
|
102 </table> |
|
103 </body> |
|
104 </html> |
|
105 """ |
|
106 |
|
107 # Return a hashtable of RE's, RM's and Teams keyed by component path. |
|
108 def read_owners(owners_file): |
|
109 if debug: |
|
110 print >> sys.stderr, "Reading %s" % owners_file |
|
111 try: |
|
112 fin = open(owners_file, 'r') |
|
113 lines = fin.readlines() |
|
114 fin.close() |
|
115 except: |
|
116 if debug: |
|
117 print >> sys.stderr, "Unable to read owners file: %s" % owners_file |
|
118 |
|
119 owners = {} |
|
120 for line in lines: |
|
121 line = line[:-1] |
|
122 component, re, rm, team = line.split("|") |
|
123 owners[component] = [ re, rm, team ] |
|
124 |
|
125 return owners |
|
126 |
|
127 # Return a hashtable of components with TPNOs keyed by component name. |
|
128 def find_TPNOs(workspace): |
|
129 comp_TPNOs = {} |
|
130 for directory, _, files in os.walk(workspace + "/components"): |
|
131 for filename in files: |
|
132 if filename.endswith(".license") or filename.endswith(".copyright"): |
|
133 pathname = os.path.join(directory, filename) |
|
134 fin = open(pathname, 'r') |
|
135 lines = fin.readlines() |
|
136 fin.close() |
|
137 |
|
138 for line in lines: |
|
139 line = line.replace("\n", "") |
|
140 if line.startswith("Oracle Internal Tracking Number"): |
|
141 tpno_str = line.split()[-1] |
|
142 try: |
|
143 # Check that the TPNO is a valid number. |
|
144 tpno = int(tpno_str) |
|
145 if debug: |
|
146 print >> sys.stderr, "TPNO: %s: %s" % \ |
|
147 (directory, tpno_str) |
|
148 comp_TPNOs[directory] = tpno_str |
|
149 except: |
|
150 print >> sys.stderr, "Unable to read TPNO: %s" % \ |
|
151 pathname |
|
152 |
|
153 return(comp_TPNOs) |
|
154 |
|
155 # Return a sorted list of the directories containing one or more .p5m files. |
|
156 def find_p5m_dirs(workspace): |
|
157 p5m_dirs = [] |
|
158 for dir, _, files in os.walk(workspace + "/components"): |
|
159 for file in files: |
|
160 if file.endswith(".p5m"): |
|
161 p5m_dirs.append(dir) |
|
162 |
|
163 return sorted(list(set(p5m_dirs))) |
|
164 |
|
165 # Write out the initial HTML for the components.html web page. |
|
166 def write_preamble(): |
|
167 print preamble |
|
168 |
|
169 # Return the RE, RM and Team for this component. |
|
170 def get_owner(p5m_dir): |
|
171 result = [ "Unknown", "Unknown", "Unknown" ] |
|
172 component_path = "" |
|
173 started = False |
|
174 tokens = p5m_dir.split("/") |
|
175 for token in tokens: |
|
176 if started: |
|
177 component_path += token + "/" |
|
178 if token == "components": |
|
179 started = True |
|
180 component_path = component_path[:-1] |
|
181 if component_path in owners: |
|
182 result = owners[component_path] |
|
183 if debug: |
|
184 print >> sys.stderr, "Component path: ", component_path, |
|
185 print >> sys.stderr, "RE, RM, Team: ", result |
|
186 |
|
187 return result |
|
188 |
|
189 # Generate an HTML table entry for all the information for the component |
|
190 # in the given directory. This generates a file called 'component-report' |
|
191 # under the components build directory. |
|
192 def gen_reports(workspace, component_dir): |
|
193 if debug: |
|
194 print >> sys.stderr, "Processing %s" % component_dir |
|
195 |
|
196 try: |
|
197 tpno = comp_TPNOs[component_dir] |
|
198 except: |
|
199 tpno = "" |
|
200 |
|
201 re, rm, team = get_owner(component_dir) |
|
202 makefiles = "-f Makefile -f %s/make-rules/component-report" % workspace |
|
203 targets = "clean component-hook" |
|
204 template = "cd %s; " |
|
205 template += "TPNO='%s' " |
|
206 template += "RESPONSIBLE_ENGINEER='%s' " |
|
207 template += "RESPONSIBLE_MANAGER='%s' " |
|
208 template += "TEAM='%s' " |
|
209 template += "gmake COMPONENT_HOOK='gmake %s component-report' %s" |
|
210 cmd = template % (component_dir, tpno, re, rm, team, makefiles, targets) |
|
211 |
|
212 if debug: |
|
213 print >> sys.stderr, "gen_reports: command: `%s`" % cmd |
|
214 lines = os.popen(cmd).readlines() |
|
215 |
|
216 # Collect all the .../build/component-report files and write them to stdout. |
|
217 def write_reports(p5m_dirs, owners_file): |
|
218 for p5m_dir in p5m_dirs: |
|
219 report = "%s/build/component-report" % p5m_dir |
|
220 if debug: |
|
221 print >> sys.stderr, "Reading %s" % report |
|
222 try: |
|
223 fin = open(report, 'r') |
|
224 lines = fin.readlines() |
|
225 fin.close() |
|
226 sys.stdout.writelines(lines) |
|
227 except: |
|
228 if debug: |
|
229 print >> sys.stderr, "Unable to read: %s" % report |
|
230 |
|
231 # Write out the final HTML for the components.html web page. |
|
232 def write_postamble(): |
|
233 print postamble |
|
234 |
|
235 # Write out a usage message showing valid options to this script. |
|
236 def usage(): |
|
237 print >> sys.stderr, \ |
|
238 """ |
|
239 Usage: |
|
240 update_man_pages.py [OPTION...] |
|
241 |
|
242 -d, --debug |
|
243 Turn on debugging |
|
244 |
|
245 -o, --owners |
|
246 Location of a file containing a list of RE's /RM's per component |
|
247 |
|
248 -w --workspace |
|
249 Location of the Userland workspace |
|
250 """ |
|
251 |
|
252 sys.exit(1) |
|
253 |
|
254 |
|
255 if __name__ == "__main__": |
|
256 workspace = os.getenv('WS_TOP') |
|
257 owners_file = "/net/userland.us.oracle.com/gates/private/RM-RE-list.txt" |
|
258 |
|
259 try: |
|
260 opts, args = getopt.getopt(sys.argv[1:], "do:w:", |
|
261 [ "debug", "owners=", "workspace=" ]) |
|
262 except getopt.GetoptError, err: |
|
263 print str(err) |
|
264 usage() |
|
265 |
|
266 for opt, arg in opts: |
|
267 if opt in [ "-d", "--debug" ]: |
|
268 debug = True |
|
269 elif opt in [ "-o", "--owners" ]: |
|
270 owners_file = arg |
|
271 elif opt in [ "-w", "--workspace" ]: |
|
272 workspace = arg |
|
273 else: |
|
274 assert False, "unknown option" |
|
275 |
|
276 owners = read_owners(owners_file) |
|
277 write_preamble() |
|
278 comp_TPNOs = find_TPNOs(workspace) |
|
279 p5m_dirs = find_p5m_dirs(workspace) |
|
280 for p5m_dir in p5m_dirs: |
|
281 gen_reports(workspace, p5m_dir) |
|
282 write_reports(p5m_dirs, owners_file) |
|
283 write_postamble() |
|
284 sys.exit(0) |