Marcel Telka
2024-04-03 72d66ff28ec33bc2c05b355c6218d98d13b79450
commit | author | age
de89cf 1 #!/usr/bin/python3.9
8dcf66 2 #
NJ 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 #
10a7de 22 # Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
8dcf66 23 #
NJ 24 #
25 # incorporator - an utility to incorporate packages in a repo
26 #
27
10a7de 28 import subprocess
AP 29 import json
30 import sys
31 import getopt
32 import re
33 import os.path
8d63c2 34 from pkg.version import Version
8dcf66 35
fb10ba 36 Werror = False        # set to true to exit with any warning
8dcf66 37
10a7de 38 def warning(msg):
AP 39     if Werror == True:
fb10ba 40         print("ERROR: %s" % msg, file=sys.stderr)
10a7de 41         sys.exit(1)
AP 42     else:
fb10ba 43         print("WARNING: %s" % msg, file=sys.stderr)
8dcf66 44
10a7de 45 class Incorporation(object):
AP 46     name = None
47     version = '5.11'
48     packages = {}
8dcf66 49
10a7de 50     def __init__(self, name, version):
AP 51         self.name = name
52         self.version = version
53         self.packages = {}
8dcf66 54
10a7de 55     def __package_to_str(self, name, version):
AP 56         # strip the :timestamp from the version string
0f39a2 57         version = version.split(':', 1)[0]
10a7de 58         # strip the ,{build-release} from the version string
0f39a2 59         version = re.sub(",[\d\.]+", "", version) 
8dcf66 60
10a7de 61         return "depend fmri=%s@%s facet.version-lock.%s=true type=incorporate" % (name, version, name)
8dcf66 62
10a7de 63     def add_package(self, name, version):
AP 64         self.packages[name] = version
8dcf66 65
10a7de 66     def __str__(self):
AP 67         result = """
68 set name=pkg.fmri value=pkg:/%s@%s
69 set name=info.classification value="org.opensolaris.category.2008:Meta Packages/Incorporations"
70 set name=org.opensolaris.consolidation value=userland
71 set name=pkg.depend.install-hold value=core-os.userland
72 set name=pkg.summary value="userland consolidation incorporation (%s)"
73 set name=pkg.description value="This incorporation constrains packages from the userland consolidation"
74 """ % (self.name, self.version, self.name)
8dcf66 75
fb10ba 76         names = list(self.packages.keys())
10a7de 77         names.sort()
AP 78         for name in names:
79             result += (self.__package_to_str(name, self.packages[name]) + '\n')
8dcf66 80
10a7de 81         return result
8dcf66 82
NJ 83 #
10a7de 84 # This should probably use the pkg APIs at some point, but this appears to be
AP 85 # a stable and less complicated interface to gathering information from the
86 # manifests in the package repo.
8dcf66 87 #
10a7de 88 def get_incorporations(repository, publisher, inc_version='5.11'):
AP 89     tmp = subprocess.Popen(["/usr/bin/pkgrepo", "list", "-F", "json",
90                                                         "-s", repository,
91                                                         "-p", publisher],
fb10ba 92                            stdout=subprocess.PIPE,
AP 93                            universal_newlines=True)
10a7de 94     incorporations = {}
AP 95     packages = json.load(tmp.stdout)
9704a4 96     inc_name='consolidation/userland/userland-incorporation'
8dcf66 97
10a7de 98     # Check for multiple versions of packages in the repo, but keep track of
AP 99     # the latest one.
100     versions = {}
101     for package in packages:
102         pkg_name = package['name']
103         pkg_version = package['version']
104
105         if pkg_name in versions:
106             warning("%s is in the repo at multiple versions (%s, %s)" % (pkg_name, pkg_version, versions[pkg_name]))
8d63c2 107             if(Version(package['version']) < Version(versions[pkg_name])):
AP 108                pkg_version = versions[pkg_name]
10a7de 109         versions[pkg_name] = pkg_version
AP 110
111     for package in packages:
112         pkg_name = package['name']
113         pkg_version = package['version']
114
115         # skip older packages and those that explicitly don't want to be incorporated
fb10ba 116         # also skip the incorporation itself
AP 117         if 'pkg.tmp.noincorporate' in package or pkg_version != versions[pkg_name] or pkg_name == inc_name:
118            continue
10a7de 119
fb10ba 120         # We don't want to support multiple incorporations for now
10a7de 121         # a dict inside a list inside a dict
AP 122         # incorporate = package['pkg.tmp.incorporate'][0]['value']
123         
124         # for inc_name in incorporate:
125             # if we haven't started to build this incorporation, create one.
126         if inc_name not in incorporations:
127            incorporations[inc_name] = Incorporation(inc_name, inc_version)
128         # find the incorporation and add the package
129         tmp = incorporations[inc_name]
130         tmp.add_package(pkg_name, pkg_version)
131     return incorporations
132
133 def main_func():
134     global Werror
135
136     try: 
137         opts, pargs = getopt.getopt(sys.argv[1:], "c:s:p:v:d:w",
138                                     ["repository=", "publisher=", "version=",
139                                      "consolidation=", "destdir=", "Werror"])
fb10ba 140     except getopt.GetoptError as e:
10a7de 141         usage(_("illegal option: %s") % e.opt)
AP 142
143     repository = None
144     publisher = None
145     version = None
146     destdir = None
147     consolidation = None
148
149     for opt, arg in opts:
150         if opt in ("-s", "--repository"):
151             repository = arg
152         elif opt in ("-p", "--publisher"):
153             publisher = arg
154         elif opt in ("-v", "--version"):
155             version = arg
156         elif opt in ("-d", "--destdir"):
157             destdir = arg
158         elif opt in ("-c", "--consolidation"):
159             consolidation = arg
160         elif opt in ("-w", "--Werror"):
161             Werror = True
162
163     incorporations = get_incorporations(repository, publisher, version)
164
fb10ba 165     for incorporation_name in list(incorporations.keys()):
10a7de 166         filename = ''
AP 167         if destdir != None:
168             filename = destdir + '/'
169         filename += os.path.basename(incorporation_name) + '.p5m'
170
171         print("Writing %s manifest to %s" % (incorporation_name, filename))
172         fd = open(filename, "w+")
173         fd.write(str(incorporations[incorporation_name]))
174         fd.close()
175
176 if __name__ == "__main__":
177     main_func()