tools/bass-o-matic
changeset 34 d20b10eba317
parent 32 280a7444e782
child 37 988ea0021850
equal deleted inserted replaced
33:371c8e56136d 34:d20b10eba317
       
     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()