tools/userland-incorporator
changeset 2142 813e4817e573
parent 1591 24aca88f3e99
child 5571 bd6c9b9b753f
equal deleted inserted replaced
2141:3b99626d1270 2142:813e4817e573
     1 #!/usr/bin/perl
     1 #!/usr/bin/python2.7
     2 #
     2 #
     3 # CDDL HEADER START
     3 # CDDL HEADER START
     4 #
     4 #
     5 # The contents of this file are subject to the terms of the
     5 # The contents of this file are subject to the terms of the
     6 # Common Development and Distribution License (the "License").
     6 # Common Development and Distribution License (the "License").
    17 # fields enclosed by brackets "[]" replaced with your own identifying
    17 # fields enclosed by brackets "[]" replaced with your own identifying
    18 # information: Portions Copyright [yyyy] [name of copyright owner]
    18 # information: Portions Copyright [yyyy] [name of copyright owner]
    19 #
    19 #
    20 # CDDL HEADER END
    20 # CDDL HEADER END
    21 #
    21 #
    22 # Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
    22 # Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
    23 #
    23 #
    24 #
    24 #
    25 # incorporator - an utility to incorporate packages in a repo
    25 # incorporator - an utility to incorporate packages in a repo
    26 #
    26 #
    27 
    27 
    28 use Getopt::Long;
    28 import subprocess
       
    29 import json
       
    30 import sys
       
    31 import getopt
       
    32 import re
       
    33 import os.path
    29 
    34 
    30 sub enumerate_packages {
    35 Werror = False	# set to true to exit with any warning
    31 	local ($repository, $publisher, @fmris) = @_;
       
    32         my @packages = ();
       
    33 
    36 
    34 	#printf "/usr/bin/pkg list -ng $repository @fmris\n";
    37 def warning(msg):
    35 	open($fp, "-|", "/usr/bin/pkgrepo", "list", "-H", "-s", $repository,
    38     if Werror == True:
    36 		  "-p", $publisher, @fmris) ||
    39         print >>sys.stderr, "ERROR: %s" % msg
    37                   die "pkg: $!";
    40         sys.exit(1)
    38 	while (<$fp>) {
    41     else:
       
    42         print >>sys.stderr, "WARNING: %s" % msg
    39 
    43 
    40 		# lines should be in the form:
    44 class Incorporation(object):
    41 		#   publisher   package   [r|o] version,5.12-branch:timestamp
    45     name = None
    42 		# or lines should be in the form:
    46     version = '5.12'
    43 		#   publisher   package   [r|o] version-branch:timestamp
    47     packages = {}
    44 		if ((/^(\S+)\s+(\S+)\s+\S?\s+([\d.]+),[\d.]+-([\d.]+):.+$/) ||
       
    45 		   (/^(\S+)\s+(\S+)\s+\S?\s+([\d.]+)-([\d.]+):.+$/)) { 
       
    46 			my ($package) = ();
       
    47 
    48 
    48 			$package->{publisher} = $1;
    49     def __init__(self, name, version):
    49 			$package->{name} = $2;
    50         self.name = name
    50 			$package->{version} = $3;
    51         self.version = version
    51 			$package->{branch} = $4;
    52         self.packages = {}
    52 
    53 
    53 			if ($package->{name} !~ m/incorporation/) {
    54     def __package_to_str(self, name, version):
    54 				push(@packages, $package);
    55         # strip the :timestamp from the version string
    55 			} 
    56         version = version.split(':', 1)[0]
    56 		} else {
    57         # strip the ,{build-release} from the version string
    57 			die "error: cannot handle: ", $_;
    58         version = re.sub(",[\d\.]+", "", version) 
    58 		}
       
    59 	}
       
    60 
    59 
    61 	#printf "returning %s\n", $_->{name} for (@packages);
    60         return "depend fmri=%s@%s facet.version-lock.%s=true type=incorporate" % (name, version, name)
    62 
    61 
    63 	return @packages;
    62     def add_package(self, name, version):
    64 }
    63         self.packages[name] = version
    65 
    64 
    66 sub print_incorporate {
    65     def __str__(self):
    67 	local (%package) = @_;
    66         result = """
    68 	my $facet = "facet.version-lock.$package->{name}";
    67 set name=pkg.fmri value=pkg:/%s@%s
       
    68 set name=info.classification value="org.opensolaris.category.2008:Meta Packages/Incorporations"
       
    69 set name=org.opensolaris.consolidation value=userland
       
    70 set name=pkg.depend.install-hold value=core-os.userland
       
    71 set name=pkg.summary value="userland consolidation incorporation (%s)"
       
    72 set name=pkg.description value="This incorporation constrains packages from the userland consolidation"
       
    73 """ % (self.name, self.version, self.name)
    69 
    74 
    70 	printf "depend fmri=%s@%s-%s %s=true type=incorporate\n",
    75         names = self.packages.keys()
    71 		$package->{name}, $package->{version}, $package->{branch},
    76         names.sort()
    72 		$facet;
    77         for name in names:
    73 }
    78             result += (self.__package_to_str(name, self.packages[name]) + '\n')
    74 
    79 
    75 my ($repository, $fmri, $summary, $description, $consolidation) = ();
    80         return result
    76 my %seen = ();
       
    77 
       
    78 $consolidation = 'userland';
       
    79 
       
    80 GetOptions("R|repository=s" => \$repository, "v|version=s" => \$version,
       
    81 	   "s|summary=s" => \$summary, "d|description=s" => \$description,
       
    82 	   "p|package=s" => \$fmri, "f|fmri=s" => \@fmris,
       
    83 	   "c|consolidation=s" => \$consolidation);
       
    84 
    81 
    85 #
    82 #
    86 # print the incorporation
    83 # This should probably use the pkg APIs at some point, but this appears to be
       
    84 # a stable and less complicated interface to gathering information from the
       
    85 # manifests in the package repo.
    87 #
    86 #
    88 printf "set name=pkg.fmri value=%s\n", $fmri;
    87 def get_incorporations(repository, publisher, inc_version='5.12'):
    89 printf "set name=pkg.summary value='%s'\n", $summary;
    88     tmp = subprocess.Popen(["/usr/bin/pkgrepo", "list", "-F", "json",
    90 printf "set name=pkg.description value='%s'\n", $description;
    89                                                         "-s", repository,
    91 printf "set name=org.opensolaris.consolidation value=%s\n",
    90                                                         "-p", publisher],
    92 		$consolidation;
    91                            stdout=subprocess.PIPE)
    93 printf "set name=pkg.depend.install-hold value=core-os.%s\n",
    92     incorporations = {}
    94 		$consolidation;
    93     packages = json.load(tmp.stdout)
    95 printf "set name=info.classification value='org.opensolaris.category.2008:Meta Packages/Incorporations'\n";
       
    96 
    94 
    97 @packages = enumerate_packages($repository, $consolidation, @fmris);
    95     # Check for multiple versions of packages in the repo, but keep track of
       
    96     # the latest one.
       
    97     versions = {}
       
    98     for package in packages:
       
    99         pkg_name = package['name']
       
   100         pkg_version = package['version']
    98 
   101 
    99 for (@packages) {
   102         if pkg_name in versions:
   100 	if ($seen->{$_->{name}} == 1) {
   103             warning("%s is in the repo at multiple versions (%s, %s)" % (pkg_name, pkg_version, versions[pkg_name]))
   101 		die "error: duplicate package ", $_->{name};
   104             pkg_version = max(pkg_version, versions[pkg_name])
   102 	}
   105         versions[pkg_name] = pkg_version
   103 	printf "depend fmri=pkg:/%s@%s-%s %s=true type=incorporate\n",
   106 
   104 		$_->{name}, $_->{version}, $_->{branch},
   107     for package in packages:
   105 		"facet.version-lock.".$_->{name}; 
   108         pkg_name = package['name']
   106 	$seen->{$_->{name}} = 1;
   109         pkg_version = package['version']
   107 }
   110 
       
   111         # skip older packages and those that don't want to be incorporated
       
   112         if 'pkg.tmp.incorporate' not in package or pkg_version != versions[pkg_name]:
       
   113             continue
       
   114 
       
   115         # a dict inside a list inside a dict
       
   116         incorporate = package['pkg.tmp.incorporate'][0]['value']
       
   117         
       
   118         for inc_name in incorporate:
       
   119             # if we haven't started to build this incorporation, create one.
       
   120             if inc_name not in incorporations:
       
   121                 incorporations[inc_name] = Incorporation(inc_name, inc_version)
       
   122             # find the incorporation and add the package
       
   123             tmp = incorporations[inc_name]
       
   124             tmp.add_package(pkg_name, pkg_version)
       
   125     return incorporations
       
   126 
       
   127 def main_func():
       
   128     global Werror
       
   129 
       
   130     try: 
       
   131         opts, pargs = getopt.getopt(sys.argv[1:], "c:s:p:v:d:w",
       
   132                                     ["repository=", "publisher=", "version=",
       
   133                                      "consolidation=", "destdir=", "Werror"])
       
   134     except getopt.GetoptError, e:
       
   135         usage(_("illegal option: %s") % e.opt)
       
   136 
       
   137     repository = None
       
   138     publisher = None
       
   139     version = None
       
   140     destdir = None
       
   141     consolidation = None
       
   142 
       
   143     for opt, arg in opts:
       
   144         if opt in ("-s", "--repository"):
       
   145             repository = arg
       
   146         elif opt in ("-p", "--publisher"):
       
   147             publisher = arg
       
   148         elif opt in ("-v", "--version"):
       
   149             version = arg
       
   150         elif opt in ("-d", "--destdir"):
       
   151             destdir = arg
       
   152         elif opt in ("-c", "--consolidation"):
       
   153             consolidation = arg
       
   154         elif opt in ("-w", "--Werror"):
       
   155             Werror = True
       
   156 
       
   157     incorporations = get_incorporations(repository, publisher, version)
       
   158 
       
   159     for incorporation_name in incorporations.keys():
       
   160         filename = ''
       
   161         if destdir != None:
       
   162             filename = destdir + '/'
       
   163         filename += os.path.basename(incorporation_name) + '.p5m'
       
   164 
       
   165         print("Writing %s manifest to %s" % (incorporation_name, filename))
       
   166         fd = open(filename, "w+")
       
   167         fd.write(str(incorporations[incorporation_name]))
       
   168         fd.close()
       
   169 
       
   170 if __name__ == "__main__":
       
   171     main_func()