drm: illumos/gfx-drm integration
[unleashed-userland.git] / tools / userland-mangler
blobe642440de66934e8cfcc767ec06ea5cf356d3793
1 #!/usr/bin/python2.7
3 # CDDL HEADER START
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]
20 # CDDL HEADER END
22 # Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
25 # userland-mangler - a file mangling utility
27 #  A simple program to mangle files to conform to Solaris WOS or Consoldation
28 #  requirements.
31 import os
32 import sys
33 import re
35 import pkg.fmri
36 import pkg.manifest
37 import pkg.actions
38 import pkg.elf as elf
40 attribute_oracle_table_header = """
41 .\\\" Oracle has added the ARC stability level to this manual page"""
43 attribute_table_header = """
44 .SH ATTRIBUTES
45 See
46 .BR attributes (5)
47 for descriptions of the following attributes:
48 .sp
49 .TS
50 box;
51 cbp-1 | cbp-1
52 l | l .
53 ATTRIBUTE TYPE  ATTRIBUTE VALUE """
55 attribute_table_availability = """
57 Availability    %s"""
59 attribute_table_stability = """
61 Stability       %s"""
63 attribute_table_footer = """
64 .TE 
65 .PP
66 """
67 def attributes_section_text(availability, stability, modified_date):
68         result = ''
70         # is there anything to do?
71         if availability is not None or stability is not None:
72                 result = attribute_oracle_table_header
73                 if modified_date is not None:
74                         result += ("\n.\\\" on %s" % modified_date)
75                 result += attribute_table_header
77                 if availability is not None:
78                         result += (attribute_table_availability % availability)
79                 if stability is not None:
80                         result += (attribute_table_stability % stability.capitalize())
81                 result += attribute_table_footer
83         return result
85 notes_oracle_comment = """
86 .\\\" Oracle has added source availability information to this manual page"""
88 notes_header = """
89 .SH NOTES
90 """
92 notes_community = """
93 Further information about this software can be found on the open source community website at %s.
94 """
95 notes_source = """
96 This software was built from source available at http://opensolaris.org/.  The original community source was downloaded from  %s
97 """
99 def notes_section_text(header_seen, community, source, modified_date):
100         result = ''
102         # is there anything to do?
103         if community is not None or source is not None:
104                 if header_seen == False:
105                         result += notes_header
106                 result += notes_oracle_comment
107                 if modified_date is not None:
108                         result += ("\n.\\\" on %s" % modified_date)
109                 if source is not None:
110                         result += (notes_source % source)
111                 if community is not None:
112                         result += (notes_community % community)
114         return result
116 so_re = re.compile('^\.so.+$', re.MULTILINE)
117 section_re = re.compile('\.SH "?([^"]+).*$', re.IGNORECASE)
119 # mangler.man.stability = (mangler.man.stability)
120 # mangler.man.modified_date = (mangler.man.modified-date)
121 # mangler.man.availability = (pkg.fmri)
122 # mangler.man.source-url = (pkg.source-url)
123 # mangler.man.upstream-url = (pkg.upstream-url)
125 def mangle_manpage(manifest, action, text):
126         # manpages must have a taxonomy defined
127         stability = action.attrs.pop('mangler.man.stability', None)
128         if stability is None:
129                 sys.stderr.write("ERROR: manpage action missing mangler.man.stability: %s" % action)
130                 sys.exit(1)
132         # manpages may have a 'modified date'
133         modified_date = action.attrs.pop('mangler.man.modified-date', None)
135         attributes_written = False
136         notes_seen = False
138         if 'pkg.fmri' in manifest.attributes:
139                 fmri = pkg.fmri.PkgFmri(manifest.attributes['pkg.fmri'])
140                 availability = fmri.pkg_name
142         community = None
143         if 'info.upstream-url' in manifest.attributes:
144                 community = manifest.attributes['info.upstream-url']
146         source = None
147         if 'info.source-url' in manifest.attributes:
148                 source = manifest.attributes['info.source-url']
149         elif 'info.repository-url' in manifest.attributes:
150                 source = manifest.attributes['info.repository-url']
152         # skip reference only pages
153         if so_re.match(text) is not None:
154                 return text
156         # tell man that we want tables (and eqn)
157         result = "'\\\" te\n"
159         # write the orginal data
160         for line in text.split('\n'):
161                 match = section_re.match(line)
162                 if match is not None:
163                         section = match.group(1)
164                         if section in ['SEE ALSO', 'NOTES']:
165                                 if attributes_written == False:
166                                         result += attributes_section_text(
167                                                                  availability,
168                                                                  stability,
169                                                                  modified_date)
170                                         attributes_written = True
171                                 if section == 'NOTES':
172                                         notes_seen = True
173                 result += ("%s\n" % line)
175         if attributes_written == False:
176                 result += attributes_section_text(availability, stability,
177                     modified_date)
179         result += notes_section_text(notes_seen, community, source,
180             modified_date)
182         return result
186 # mangler.elf.strip = (true|false)
188 def mangle_elf(manifest, action, src, dest):
189         pass
192 # mangler.script.file-magic =
194 def mangle_script(manifest, action, text):
195         return text
198 # mangler.strip_cddl = false
200 def mangle_cddl(manifest, action, text):
201         strip_cddl = action.attrs.pop('mangler.strip_cddl', 'true')
202         if strip_cddl is 'false':
203                 return text
204         cddl_re = re.compile('^[^\n]*CDDL HEADER START.+CDDL HEADER END[^\n]*$',
205                              re.MULTILINE|re.DOTALL)
206         return cddl_re.sub('', text)
208 def mangle_path(manifest, action, src, dest):
209         if elf.is_elf_object(src):
210                 mangle_elf(manifest, action, src, dest)
211         else:
212                 # a 'text' document (script, man page, config file, ...
213                 ifp = open(src, 'r')
214                 text = ifp.read()
215                 ifp.close()
217                 # remove the CDDL from files
218                 result = mangle_cddl(manifest, action, text)
220                 if 'facet.doc.man' in action.attrs:
221                         result = mangle_manpage(manifest, action, result)
222                 elif 'mode' in action.attrs and int(action.attrs['mode'], 8) & 0111 != 0:
223                         result = mangle_script(manifest, action, result)
225                 if text != result:
226                         destdir = os.path.dirname(dest)
227                         if not os.path.exists(destdir):
228                                 os.makedirs(destdir)
229                         with open(dest, 'w') as ofp:
230                             ofp.write(result)
233 # mangler.bypass = (true|false)
235 def mangle_paths(manifest, search_paths, destination):
236         for action in manifest.gen_actions_by_type("file"):
237                 bypass = action.attrs.pop('mangler.bypass', 'false').lower()
238                 if bypass == 'true':
239                         continue
241                 path = None
242                 if 'path' in action.attrs:
243                         path = action.attrs['path']
244                 if action.hash and action.hash != 'NOHASH':
245                         path = action.hash
246                 if not path:
247                         continue
249                 if not os.path.exists(destination):
250                         os.makedirs(destination)
252                 dest = os.path.join(destination, path)
253                 for directory in search_paths:
254                         if directory != destination:
255                                 src = os.path.join(directory, path)
256                                 if os.path.isfile(src):
257                                         mangle_path(manifest, action, src, dest)
258                                         break
260 def load_manifest(manifest_file):
261         manifest = pkg.manifest.Manifest()
262         manifest.set_content(pathname=manifest_file)
264         return manifest
266 def usage():
267         print "Usage: %s [-m|--manifest (file)] [-d|--search-directory (dir)] [-D|--destination (dir)] " % (sys.argv[0].split('/')[-1])
268         sys.exit(1)
270 def main():
271         import getopt
273         # FLUSH STDOUT 
274         sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
276         search_paths = []
277         destination = None
278         manifests = []
280         try:
281                 opts, args = getopt.getopt(sys.argv[1:], "D:d:m:",
282                         ["destination=", "search-directory=", "manifest="])
283         except getopt.GetoptError, err:
284                 print str(err)
285                 usage()
287         for opt, arg in opts:
288                 if opt in [ "-D", "--destination" ]:
289                         destination = arg
290                 elif opt in [ "-d", "--search-directory" ]:
291                         search_paths.append(arg)
292                 elif opt in [ "-m", "--manifest" ]:
293                         try:
294                                 manifest = load_manifest(arg)
295                         except IOError, err:
296                                 print "oops, %s: %s" % (arg, str(err))
297                                 usage()
298                         else:
299                                 manifests.append(manifest)
300                 else:
301                         usage()
303         if destination == None:
304                 usage()
306         for manifest in manifests:
307                 mangle_paths(manifest, search_paths, destination)
308                 print manifest
310         sys.exit(0)
312 if __name__ == "__main__":
313         main()