3468N/A#!/usr/bin/python2.7
500N/A#
500N/A# CDDL HEADER START
500N/A#
500N/A# The contents of this file are subject to the terms of the
500N/A# Common Development and Distribution License (the "License").
500N/A# You may not use this file except in compliance with the License.
500N/A#
500N/A# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
500N/A# or http://www.opensolaris.org/os/licensing.
500N/A# See the License for the specific language governing permissions
500N/A# and limitations under the License.
500N/A#
500N/A# When distributing Covered Code, include this CDDL HEADER in each
500N/A# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
500N/A# If applicable, add the following below this CDDL HEADER, with the
500N/A# fields enclosed by brackets "[]" replaced with your own identifying
500N/A# information: Portions Copyright [yyyy] [name of copyright owner]
500N/A#
500N/A# CDDL HEADER END
500N/A#
7034N/A# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
500N/A#
500N/A#
500N/A# incorporator - an utility to incorporate packages in a repo
500N/A#
500N/A
3468N/Aimport subprocess
3468N/Aimport json
3468N/Aimport sys
3468N/Aimport getopt
3468N/Aimport re
3468N/Aimport os.path
500N/A
3468N/AWerror = False # set to true to exit with any warning
500N/A
3468N/Adef warning(msg):
3468N/A if Werror == True:
3468N/A print >>sys.stderr, "ERROR: %s" % msg
3468N/A sys.exit(1)
3468N/A else:
3468N/A print >>sys.stderr, "WARNING: %s" % msg
500N/A
3468N/Aclass Incorporation(object):
3468N/A name = None
3468N/A version = '5.12'
3468N/A packages = {}
3468N/A
3468N/A def __init__(self, name, version):
3468N/A self.name = name
3468N/A self.version = version
3468N/A self.packages = {}
500N/A
3468N/A def __package_to_str(self, name, version):
3468N/A # strip the :timestamp from the version string
3468N/A version = version.split(':', 1)[0]
3468N/A # strip the ,{build-release} from the version string
3468N/A version = re.sub(",[\d\.]+", "", version)
500N/A
3468N/A return "depend fmri=%s@%s facet.version-lock.%s=true type=incorporate" % (name, version, name)
500N/A
3468N/A def add_package(self, name, version):
3468N/A self.packages[name] = version
500N/A
3468N/A def __str__(self):
3468N/A result = """
3468N/Aset name=pkg.fmri value=pkg:/%s@%s
3468N/Aset name=info.classification value="org.opensolaris.category.2008:Meta Packages/Incorporations"
3468N/Aset name=org.opensolaris.consolidation value=userland
3468N/Aset name=pkg.depend.install-hold value=core-os.userland
3468N/Aset name=pkg.summary value="userland consolidation incorporation (%s)"
3468N/Aset name=pkg.description value="This incorporation constrains packages from the userland consolidation"
3468N/A""" % (self.name, self.version, self.name)
500N/A
3468N/A names = self.packages.keys()
3468N/A names.sort()
3468N/A for name in names:
3468N/A result += (self.__package_to_str(name, self.packages[name]) + '\n')
500N/A
3468N/A return result
500N/A
500N/A#
3468N/A# This should probably use the pkg APIs at some point, but this appears to be
3468N/A# a stable and less complicated interface to gathering information from the
3468N/A# manifests in the package repo.
500N/A#
7034N/Adef get_incorporations(repository, publisher, inc_version='5.12',
7034N/A static_file=None):
7034N/A packages = {}
3468N/A incorporations = {}
7034N/A versions = {}
7034N/A
7034N/A #
7034N/A # if a static file was provided, prime the cache with the contents of
7034N/A # that file.
7034N/A #
7034N/A if static_file:
7034N/A with open(static_file, 'r') as fp:
7034N/A for line in fp:
7034N/A line = line.partition('#')[0]
7034N/A line = line.rstrip()
3468N/A
7034N/A try:
7034N/A (incorporation, package, version) = re.split(':|@', line)
7034N/A except ValueError:
7034N/A pass
7034N/A else:
7034N/A if "=i386" in version:
7034N/A if repository.rsplit('/',2)[1] == "i386":
7034N/A version = version.split('=',1)[0]
7034N/A else:
7034N/A continue
7034N/A if incorporation not in incorporations:
7034N/A incorporations[incorporation] = Incorporation(incorporation, inc_version)
7034N/A # find the incorporation and add the package
7034N/A tmp = incorporations[incorporation]
7034N/A tmp.add_package(package, version)
7034N/A versions[package] = version
7034N/A
7034N/A #
7034N/A # Load the repository for packages to incorporate.
7034N/A #
7034N/A if repository:
7034N/A tmp = subprocess.Popen(["/usr/bin/pkgrepo", "list", "-F", "json",
7034N/A "-s", repository,
7034N/A "-p", publisher],
7034N/A stdout=subprocess.PIPE)
7034N/A packages = json.load(tmp.stdout)
7034N/A
7034N/A #
3468N/A # Check for multiple versions of packages in the repo, but keep track of
3468N/A # the latest one.
7034N/A #
3468N/A for package in packages:
3468N/A pkg_name = package['name']
3468N/A pkg_version = package['version']
3468N/A
3468N/A if pkg_name in versions:
3468N/A warning("%s is in the repo at multiple versions (%s, %s)" % (pkg_name, pkg_version, versions[pkg_name]))
3468N/A pkg_version = max(pkg_version, versions[pkg_name])
3468N/A versions[pkg_name] = pkg_version
3468N/A
7034N/A #
7034N/A # Add published packages to the incorporation lists
7034N/A #
3468N/A for package in packages:
3468N/A pkg_name = package['name']
3468N/A pkg_version = package['version']
3468N/A
3468N/A # skip older packages and those that don't want to be incorporated
3468N/A if 'pkg.tmp.incorporate' not in package or pkg_version != versions[pkg_name]:
3468N/A continue
3468N/A
3468N/A # a dict inside a list inside a dict
3468N/A incorporate = package['pkg.tmp.incorporate'][0]['value']
3468N/A
3468N/A for inc_name in incorporate:
3468N/A # if we haven't started to build this incorporation, create one.
3468N/A if inc_name not in incorporations:
3468N/A incorporations[inc_name] = Incorporation(inc_name, inc_version)
3468N/A # find the incorporation and add the package
3468N/A tmp = incorporations[inc_name]
3468N/A tmp.add_package(pkg_name, pkg_version)
7034N/A
3468N/A return incorporations
500N/A
3468N/Adef main_func():
3468N/A global Werror
3468N/A
3468N/A try:
7034N/A opts, pargs = getopt.getopt(sys.argv[1:], "S:c:s:p:v:d:w",
3468N/A ["repository=", "publisher=", "version=",
7034N/A "consolidation=", "destdir=", "Werror",
7034N/A "static-content-file="])
3468N/A except getopt.GetoptError, e:
3468N/A usage(_("illegal option: %s") % e.opt)
3468N/A
7034N/A static_file = None
3468N/A repository = None
3468N/A publisher = None
3468N/A version = None
3468N/A destdir = None
3468N/A consolidation = None
2238N/A
3468N/A for opt, arg in opts:
7034N/A if opt in ("-S", "--static-content-file"):
7034N/A static_file = arg
7034N/A elif opt in ("-s", "--repository"):
3468N/A repository = arg
3468N/A elif opt in ("-p", "--publisher"):
3468N/A publisher = arg
3468N/A elif opt in ("-v", "--version"):
3468N/A version = arg
3468N/A elif opt in ("-d", "--destdir"):
3468N/A destdir = arg
3468N/A elif opt in ("-c", "--consolidation"):
3468N/A consolidation = arg
3468N/A elif opt in ("-w", "--Werror"):
3468N/A Werror = True
3468N/A
7034N/A incorporations = get_incorporations(repository, publisher, version,
7034N/A static_file)
3468N/A
3468N/A for incorporation_name in incorporations.keys():
3468N/A filename = ''
3468N/A if destdir != None:
3468N/A filename = destdir + '/'
3468N/A filename += os.path.basename(incorporation_name) + '.p5m'
3468N/A
3468N/A print("Writing %s manifest to %s" % (incorporation_name, filename))
3468N/A fd = open(filename, "w+")
3468N/A fd.write(str(incorporations[incorporation_name]))
3468N/A fd.close()
3468N/A
3468N/Aif __name__ == "__main__":
3468N/A main_func()