bass-o-matic revision 3770
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg#!/usr/bin/python2.7
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg#
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# CDDL HEADER START
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg#
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# The contents of this file are subject to the terms of the
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# Common Development and Distribution License (the "License").
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# You may not use this file except in compliance with the License.
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg#
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# or http://www.opensolaris.org/os/licensing.
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# See the License for the specific language governing permissions
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# and limitations under the License.
0662ed52e814f8f08ef0e09956413a792584eddffuankg#
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# When distributing Covered Code, include this CDDL HEADER in each
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# If applicable, add the following below this CDDL HEADER, with the
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# fields enclosed by brackets "[]" replaced with your own identifying
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# information: Portions Copyright [yyyy] [name of copyright owner]
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg#
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# CDDL HEADER END
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg#
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg#
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg#
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# bass-o-matic.py
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# A simple program to enumerate components in the userland gate and report
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# on dependency related information.
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg#
44f575c8cb19a7a5cd61664a7848be6bc197df02fuankg
16b55a35cff91315d261d1baa776138af465c4e4fuankgimport os
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankgimport sys
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankgimport re
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankgimport subprocess
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# Locate SCM directories containing Userland components by searching from
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# from a supplied top of tree for .p5m files. Once a .p5m file is located,
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg# that directory is added to the list and no children are searched.
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankgdef FindComponentPaths(path, debug=None):
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg expression = re.compile(".+\.p5m$", re.IGNORECASE)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg paths = []
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg if debug:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg print >>debug, "searching %s for component directories" % path
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg for dirpath, dirnames, filenames in os.walk(path + '/components'):
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg found = 0
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg for name in filenames:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg if expression.match(name):
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg if debug:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg print >>debug, "found %s" % dirpath
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg paths.append(dirpath)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg del dirnames[:]
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg break
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg return sorted(paths)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankgclass BassComponent:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg def __init__(self, path=None, debug=None):
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg self.debug = debug
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg self.path = path
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg if path:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg # get supplied packages (cd path ; gmake print-package-names)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg self.supplied_packages = self.run_make(path, 'print-package-names')
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg # get supplied paths (cd path ; gmake print-package-paths)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg self.supplied_paths = self.run_make(path, 'print-package-paths')
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg # get required paths (cd path ; gmake print-required-paths)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg self.required_paths = self.run_make(path, 'print-required-paths')
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg def required(self, component):
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg result = False
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg s1 = set(self.required_paths)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg s2 = set(component.supplied_paths)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg if s1.intersection(s2):
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg result = True
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg return result
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg def run_make(self, path, targets):
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg result = list()
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg if self.debug:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg print >>self.debug, "Executing 'gmake %s' in %s" % (targets, path)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg proc = subprocess.Popen(['gmake', targets], cwd=path,
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg stdout=subprocess.PIPE, stderr=subprocess.PIPE)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg p = proc.stdout
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg for out in p:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg result.append(out)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg if self.debug:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg proc.wait()
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg if proc.returncode != 0:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg print >>self.debug, "exit: %d, %s" % (proc.returncode, proc.stderr.read())
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg return result
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg def __str__(self):
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg result = "Component:\n\tPath: %s\n" % self.path
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg result = result + "\tProvides Package(s):\n\t\t%s\n" % '\t\t'.join(self.supplied_packages)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg result = result + "\tProvides Path(s):\n\t\t%s\n" % '\t\t'.join(self.supplied_paths)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg result = result + "\tRequired Path(s):\n\t\t%s\n" % '\t\t'.join(self.required_paths)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg return result
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankgdef usage():
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg print "Usage: %s [-c|--components=(path|depend)] [-z|--zone (zone)]" % (sys.argv[0].split('/')[-1])
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg sys.exit(1)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankgdef main():
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg import getopt
0662ed52e814f8f08ef0e09956413a792584eddffuankg import sys
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg # FLUSH STDOUT
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg components = {}
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg debug=None
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg components_arg=None
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg make_arg=None
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg component_arg=None
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg template_zone=None
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg workspace = os.getenv('WS_TOP')
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
0662ed52e814f8f08ef0e09956413a792584eddffuankg try:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg opts, args = getopt.getopt(sys.argv[1:], "w:c:d",
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg [ "debug", "workspace=", "components=",
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg "make", "component=", "template-zone=" ])
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg except getopt.GetoptError, err:
0662ed52e814f8f08ef0e09956413a792584eddffuankg print str(err)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg usage()
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg for opt, arg in opts:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg if opt in [ "-w", "--workspace" ]:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg workspace = arg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg elif opt in [ "-l", "--components" ]:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg components_arg = arg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg elif opt in [ "--make" ]:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg make_arg = True
0662ed52e814f8f08ef0e09956413a792584eddffuankg elif opt in [ "--component" ]:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg component_arg = arg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg elif opt in [ "--template-zone" ]:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg template_zone = arg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg elif opt in [ "-d", "--debug" ]:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg debug = sys.stdout
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg else:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg assert False, "unknown option"
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg component_paths = FindComponentPaths(workspace, debug)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg if make_arg:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg if template_zone:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg print "using template zone %s to create a build environment for %s to run '%s'" % (template_zone, component_arg, ['gmake'] + args)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg proc = subprocess.Popen(['gmake'] + args)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg rc = proc.wait()
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg sys.exit(rc)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg if components_arg:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg if components_arg in [ 'path', 'paths', 'dir', 'dirs', 'directories' ]:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg for path in component_paths:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg print "%s" % path
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg elif components_arg in [ 'depend', 'dependencies' ]:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg for path in component_paths:
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg components[path] = BassComponent(path, debug)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg for c_path in components.keys():
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg component = components[c_path]
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg for d_path in components.keys():
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg if (c_path != d_path and
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg component.required(components[d_path])):
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg print "%s: %s" % (c_path, d_path)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
cf7ca2f9eaa6523fefcccba4287b91637391fb51fuankg sys.exit(0)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg sys.exit(1)
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankgif __name__ == "__main__":
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg main()
ff7e89a077d93c243bd8261cf3c72b13732ab5b4fuankg