diff -r b125568c3ea5 -r c35c8f1a6df1 tools/userland-incorporator --- a/tools/userland-incorporator Tue Nov 18 17:39:37 2014 -0800 +++ b/tools/userland-incorporator Fri Oct 10 10:07:08 2014 -0700 @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/python2.7 # # CDDL HEADER START # @@ -19,89 +19,153 @@ # # CDDL HEADER END # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # # # incorporator - an utility to incorporate packages in a repo # -use Getopt::Long; - -sub enumerate_packages { - local ($repository, $publisher, @fmris) = @_; - my @packages = (); +import subprocess +import json +import sys +import getopt +import re +import os.path - #printf "/usr/bin/pkg list -ng $repository @fmris\n"; - open($fp, "-|", "/usr/bin/pkgrepo", "list", "-H", "-s", $repository, - "-p", $publisher, @fmris) || - die "pkg: $!"; - while (<$fp>) { +Werror = False # set to true to exit with any warning - # lines should be in the form: - # publisher package [r|o] version,5.12-branch:timestamp - # or lines should be in the form: - # publisher package [r|o] version-branch:timestamp - if ((/^(\S+)\s+(\S+)\s+\S?\s+([\d.]+),[\d.]+-([\d.]+):.+$/) || - (/^(\S+)\s+(\S+)\s+\S?\s+([\d.]+)-([\d.]+):.+$/)) { - my ($package) = (); +def warning(msg): + if Werror == True: + print >>sys.stderr, "ERROR: %s" % msg + sys.exit(1) + else: + print >>sys.stderr, "WARNING: %s" % msg - $package->{publisher} = $1; - $package->{name} = $2; - $package->{version} = $3; - $package->{branch} = $4; +class Incorporation(object): + name = None + version = '5.12' + packages = {} + + def __init__(self, name, version): + self.name = name + self.version = version + self.packages = {} - if ($package->{name} !~ m/incorporation/) { - push(@packages, $package); - } - } else { - die "error: cannot handle: ", $_; - } - } + def __package_to_str(self, name, version): + # strip the :timestamp from the version string + version = version.split(':', 1)[0] + # strip the ,{build-release} from the version string + version = re.sub(",[\d\.]+", "", version) - #printf "returning %s\n", $_->{name} for (@packages); + return "depend fmri=%s@%s facet.version-lock.%s=true type=incorporate" % (name, version, name) - return @packages; -} + def add_package(self, name, version): + self.packages[name] = version -sub print_incorporate { - local (%package) = @_; - my $facet = "facet.version-lock.$package->{name}"; - - printf "depend fmri=%s@%s-%s %s=true type=incorporate\n", - $package->{name}, $package->{version}, $package->{branch}, - $facet; -} + def __str__(self): + result = """ +set name=pkg.fmri value=pkg:/%s@%s +set name=info.classification value="org.opensolaris.category.2008:Meta Packages/Incorporations" +set name=org.opensolaris.consolidation value=userland +set name=pkg.depend.install-hold value=core-os.userland +set name=pkg.summary value="userland consolidation incorporation (%s)" +set name=pkg.description value="This incorporation constrains packages from the userland consolidation" +""" % (self.name, self.version, self.name) -my ($repository, $fmri, $summary, $description, $consolidation) = (); -my %seen = (); - -$consolidation = 'userland'; + names = self.packages.keys() + names.sort() + for name in names: + result += (self.__package_to_str(name, self.packages[name]) + '\n') -GetOptions("R|repository=s" => \$repository, "v|version=s" => \$version, - "s|summary=s" => \$summary, "d|description=s" => \$description, - "p|package=s" => \$fmri, "f|fmri=s" => \@fmris, - "c|consolidation=s" => \$consolidation); + return result # -# print the incorporation +# This should probably use the pkg APIs at some point, but this appears to be +# a stable and less complicated interface to gathering information from the +# manifests in the package repo. # -printf "set name=pkg.fmri value=%s\n", $fmri; -printf "set name=pkg.summary value='%s'\n", $summary; -printf "set name=pkg.description value='%s'\n", $description; -printf "set name=org.opensolaris.consolidation value=%s\n", - $consolidation; -printf "set name=pkg.depend.install-hold value=core-os.%s\n", - $consolidation; -printf "set name=info.classification value='org.opensolaris.category.2008:Meta Packages/Incorporations'\n"; +def get_incorporations(repository, publisher, inc_version='5.12'): + tmp = subprocess.Popen(["/usr/bin/pkgrepo", "list", "-F", "json", + "-s", repository, + "-p", publisher], + stdout=subprocess.PIPE) + incorporations = {} + packages = json.load(tmp.stdout) + + # Check for multiple versions of packages in the repo, but keep track of + # the latest one. + versions = {} + for package in packages: + pkg_name = package['name'] + pkg_version = package['version'] + + if pkg_name in versions: + warning("%s is in the repo at multiple versions (%s, %s)" % (pkg_name, pkg_version, versions[pkg_name])) + pkg_version = max(pkg_version, versions[pkg_name]) + versions[pkg_name] = pkg_version + + for package in packages: + pkg_name = package['name'] + pkg_version = package['version'] + + # skip older packages and those that don't want to be incorporated + if 'pkg.tmp.incorporate' not in package or pkg_version != versions[pkg_name]: + continue + + # a dict inside a list inside a dict + incorporate = package['pkg.tmp.incorporate'][0]['value'] + + for inc_name in incorporate: + # if we haven't started to build this incorporation, create one. + if inc_name not in incorporations: + incorporations[inc_name] = Incorporation(inc_name, inc_version) + # find the incorporation and add the package + tmp = incorporations[inc_name] + tmp.add_package(pkg_name, pkg_version) + return incorporations -@packages = enumerate_packages($repository, $consolidation, @fmris); +def main_func(): + global Werror + + try: + opts, pargs = getopt.getopt(sys.argv[1:], "c:s:p:v:d:w", + ["repository=", "publisher=", "version=", + "consolidation=", "destdir=", "Werror"]) + except getopt.GetoptError, e: + usage(_("illegal option: %s") % e.opt) + + repository = None + publisher = None + version = None + destdir = None + consolidation = None -for (@packages) { - if ($seen->{$_->{name}} == 1) { - die "error: duplicate package ", $_->{name}; - } - printf "depend fmri=pkg:/%s@%s-%s %s=true type=incorporate\n", - $_->{name}, $_->{version}, $_->{branch}, - "facet.version-lock.".$_->{name}; - $seen->{$_->{name}} = 1; -} + for opt, arg in opts: + if opt in ("-s", "--repository"): + repository = arg + elif opt in ("-p", "--publisher"): + publisher = arg + elif opt in ("-v", "--version"): + version = arg + elif opt in ("-d", "--destdir"): + destdir = arg + elif opt in ("-c", "--consolidation"): + consolidation = arg + elif opt in ("-w", "--Werror"): + Werror = True + + incorporations = get_incorporations(repository, publisher, version) + + for incorporation_name in incorporations.keys(): + filename = '' + if destdir != None: + filename = destdir + '/' + filename += os.path.basename(incorporation_name) + '.p5m' + + print("Writing %s manifest to %s" % (incorporation_name, filename)) + fd = open(filename, "w+") + fd.write(str(incorporations[incorporation_name])) + fd.close() + +if __name__ == "__main__": + main_func()