2019-09-04 13:08:11 -03:00
|
|
|
#!/usr/bin/python3
|
2011-01-13 19:10:37 -06:00
|
|
|
#
|
|
|
|
# Check components of build dependencies and warn about universe/multiverse
|
|
|
|
# ones, for a package destined for main/restricted
|
|
|
|
#
|
|
|
|
# Copyright (C) 2011 Canonical
|
|
|
|
#
|
|
|
|
# Authors:
|
|
|
|
# Martin Pitt
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify it under
|
|
|
|
# the terms of the GNU General Public License as published by the Free Software
|
|
|
|
# Foundation; version 3.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
|
|
# details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License along with
|
|
|
|
# this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
|
2023-01-30 23:10:31 +01:00
|
|
|
# pylint: disable=invalid-name
|
|
|
|
# pylint: enable=invalid-name
|
|
|
|
|
2023-01-31 13:33:18 +01:00
|
|
|
"""Check if any of a package's build or binary dependencies are in universe or multiverse.
|
|
|
|
|
|
|
|
Run this inside an unpacked source package
|
|
|
|
"""
|
|
|
|
|
|
|
|
import argparse
|
2011-01-14 11:09:21 +01:00
|
|
|
import os.path
|
2023-01-30 21:28:47 +01:00
|
|
|
import sys
|
2011-01-13 19:10:37 -06:00
|
|
|
|
2012-05-05 19:37:41 +02:00
|
|
|
import apt
|
|
|
|
|
|
|
|
|
2011-01-14 11:09:21 +01:00
|
|
|
def check_support(apt_cache, pkgname, alt=False):
|
2023-01-30 19:45:36 +01:00
|
|
|
"""Check if pkgname is in main or restricted.
|
2011-01-13 19:10:37 -06:00
|
|
|
|
|
|
|
This prints messages if a package is not in main/restricted, or only
|
2011-01-14 11:09:21 +01:00
|
|
|
partially (i. e. source in main, but binary in universe).
|
2023-01-30 19:45:36 +01:00
|
|
|
"""
|
2011-01-13 19:10:37 -06:00
|
|
|
if alt:
|
2023-01-30 19:45:36 +01:00
|
|
|
prefix = " ... alternative " + pkgname
|
2011-01-13 19:10:37 -06:00
|
|
|
else:
|
2023-01-30 19:45:36 +01:00
|
|
|
prefix = " * " + pkgname
|
2011-01-13 19:10:37 -06:00
|
|
|
|
2024-01-10 20:03:44 -06:00
|
|
|
prov_packages = apt_cache.get_providing_packages(pkgname)
|
|
|
|
if pkgname in apt_cache:
|
2011-01-13 19:10:37 -06:00
|
|
|
pkg = apt_cache[pkgname]
|
2024-01-10 20:03:44 -06:00
|
|
|
|
|
|
|
# If this is a virtual package, iterate through the binary packages that
|
|
|
|
# provide this, and ensure they are all in Main. Source packages in and of
|
|
|
|
# themselves cannot provide virtual packages, only binary packages can.
|
|
|
|
elif len(prov_packages) > 0:
|
|
|
|
supported, unsupported = [], []
|
|
|
|
for pkg in prov_packages:
|
|
|
|
candidate = pkg.candidate
|
|
|
|
if candidate:
|
|
|
|
section = candidate.section
|
|
|
|
if section.startswith("universe") or section.startswith("multiverse"):
|
|
|
|
unsupported.append(pkg.name)
|
|
|
|
else:
|
|
|
|
supported.append(pkg.name)
|
|
|
|
|
|
|
|
if len(supported) > 0:
|
|
|
|
msg = "is a virtual package, which is provided by the following "
|
|
|
|
msg += "candidates in Main: " + " ".join(supported)
|
|
|
|
print(prefix, msg)
|
|
|
|
elif len(unsupported) > 0:
|
|
|
|
msg = "is a virtual package, but is only provided by the "
|
|
|
|
msg += "following non-Main candidates: " + " ".join(unsupported)
|
|
|
|
print(prefix, msg, file=sys.stderr)
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
msg = "is a virtual package that exists but is not provided by "
|
|
|
|
msg += "package currently in the archive. Proceed with caution."
|
|
|
|
print(prefix, msg, file=sys.stderr)
|
|
|
|
return False
|
|
|
|
|
|
|
|
else:
|
|
|
|
print(prefix, "does not exist", file=sys.stderr)
|
2011-01-13 19:10:37 -06:00
|
|
|
return False
|
2011-05-23 23:44:45 +02:00
|
|
|
|
2011-01-13 19:10:37 -06:00
|
|
|
section = pkg.candidate.section
|
2023-01-30 19:45:36 +01:00
|
|
|
if section.startswith("universe") or section.startswith("multiverse"):
|
2011-01-13 19:10:37 -06:00
|
|
|
# check if the source package is in main and thus will only need binary
|
|
|
|
# promotion
|
2011-01-14 11:09:21 +01:00
|
|
|
source_records = apt.apt_pkg.SourceRecords()
|
|
|
|
if not source_records.lookup(pkg.candidate.source_name):
|
2023-01-30 19:45:36 +01:00
|
|
|
print("ERROR: Cannot lookup source package for", pkg.name, file=sys.stderr)
|
|
|
|
print(prefix, "package is in", section.split("/")[0])
|
2011-01-13 19:10:37 -06:00
|
|
|
return False
|
2011-01-14 11:09:21 +01:00
|
|
|
src = apt.apt_pkg.TagSection(source_records.record)
|
2023-01-30 19:45:36 +01:00
|
|
|
if src["Section"].startswith("universe") or src["Section"].startswith("multiverse"):
|
|
|
|
print(prefix, "binary and source package is in", section.split("/")[0])
|
2011-01-13 19:10:37 -06:00
|
|
|
return False
|
2023-01-31 16:58:24 +01:00
|
|
|
|
|
|
|
print(
|
|
|
|
prefix,
|
|
|
|
"is in",
|
|
|
|
section.split("/")[0] + ", but its source",
|
|
|
|
pkg.candidate.source_name,
|
|
|
|
"is already in main; file an ubuntu-archive bug for "
|
|
|
|
"promoting the current preferred alternative",
|
|
|
|
)
|
|
|
|
return True
|
2011-01-13 19:10:37 -06:00
|
|
|
|
|
|
|
if alt:
|
2023-01-30 19:45:36 +01:00
|
|
|
print(prefix, "is already in main; consider preferring it")
|
2011-01-13 19:10:37 -06:00
|
|
|
|
|
|
|
return True
|
|
|
|
|
2014-03-18 23:54:36 +01:00
|
|
|
|
2011-01-14 11:09:21 +01:00
|
|
|
def check_build_dependencies(apt_cache, control):
|
2023-01-30 19:45:36 +01:00
|
|
|
print("Checking support status of build dependencies...")
|
2011-01-13 19:10:37 -06:00
|
|
|
|
2011-01-14 11:09:21 +01:00
|
|
|
any_unsupported = False
|
2011-01-13 19:10:37 -06:00
|
|
|
|
2023-01-30 19:45:36 +01:00
|
|
|
for field in ("Build-Depends", "Build-Depends-Indep"):
|
2011-01-13 19:24:40 -06:00
|
|
|
if field not in control.section:
|
|
|
|
continue
|
2011-01-14 11:09:21 +01:00
|
|
|
for or_group in apt.apt_pkg.parse_src_depends(control.section[field]):
|
2011-01-13 19:24:40 -06:00
|
|
|
pkgname = or_group[0][0]
|
2024-01-10 19:27:09 -06:00
|
|
|
|
|
|
|
# debhelper-compat is expected to be a build dependency of every
|
|
|
|
# package, so it is a red herring to display it in this report.
|
|
|
|
# (src:debhelper is in Ubuntu Main anyway)
|
|
|
|
if pkgname == "debhelper-compat":
|
|
|
|
continue
|
|
|
|
|
2011-01-14 11:09:21 +01:00
|
|
|
if not check_support(apt_cache, pkgname):
|
2011-01-13 19:24:40 -06:00
|
|
|
# check non-preferred alternatives
|
|
|
|
for altpkg in or_group[1:]:
|
2011-01-14 11:09:21 +01:00
|
|
|
if check_support(apt_cache, altpkg[0], alt=True):
|
2011-01-13 19:24:40 -06:00
|
|
|
break
|
|
|
|
else:
|
|
|
|
any_unsupported = True
|
|
|
|
|
2011-01-14 11:09:21 +01:00
|
|
|
return any_unsupported
|
|
|
|
|
2014-03-18 23:54:36 +01:00
|
|
|
|
2011-01-14 11:09:21 +01:00
|
|
|
def check_binary_dependencies(apt_cache, control):
|
|
|
|
any_unsupported = False
|
|
|
|
|
2023-01-30 19:45:36 +01:00
|
|
|
print("\nChecking support status of binary dependencies...")
|
2011-01-14 11:09:21 +01:00
|
|
|
while True:
|
|
|
|
try:
|
2019-09-04 13:08:11 -03:00
|
|
|
next(control)
|
2011-01-14 11:09:21 +01:00
|
|
|
except StopIteration:
|
|
|
|
break
|
|
|
|
|
2023-01-30 19:45:36 +01:00
|
|
|
for field in ("Depends", "Pre-Depends", "Recommends"):
|
2011-01-14 11:09:21 +01:00
|
|
|
if field not in control.section:
|
|
|
|
continue
|
2023-01-30 19:45:36 +01:00
|
|
|
for or_group in apt.apt_pkg.parse_src_depends(control.section[field]):
|
2011-01-14 11:09:21 +01:00
|
|
|
pkgname = or_group[0][0]
|
2023-01-30 19:45:36 +01:00
|
|
|
if pkgname.startswith("$"):
|
2011-01-14 11:09:21 +01:00
|
|
|
continue
|
|
|
|
if not check_support(apt_cache, pkgname):
|
|
|
|
# check non-preferred alternatives
|
|
|
|
for altpkg in or_group[1:]:
|
|
|
|
if check_support(apt_cache, altpkg[0], alt=True):
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
any_unsupported = True
|
|
|
|
|
|
|
|
return any_unsupported
|
|
|
|
|
2014-03-18 23:54:36 +01:00
|
|
|
|
2011-01-14 11:09:21 +01:00
|
|
|
def main():
|
2023-01-31 13:33:18 +01:00
|
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
2012-05-05 19:37:41 +02:00
|
|
|
parser.parse_args()
|
2011-01-14 11:09:21 +01:00
|
|
|
apt_cache = apt.Cache()
|
|
|
|
|
2023-01-30 19:45:36 +01:00
|
|
|
if not os.path.exists("debian/control"):
|
|
|
|
print(
|
|
|
|
"debian/control not found. You need to run this tool in a source package directory",
|
|
|
|
file=sys.stderr,
|
|
|
|
)
|
2011-01-14 11:09:21 +01:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
# get build dependencies from debian/control
|
2023-01-31 15:51:29 +01:00
|
|
|
control = apt.apt_pkg.TagFile(open("debian/control", encoding="utf-8"))
|
2019-09-04 13:08:11 -03:00
|
|
|
next(control)
|
2011-01-14 11:09:21 +01:00
|
|
|
|
|
|
|
unsupported_build_deps = check_build_dependencies(apt_cache, control)
|
|
|
|
unsupported_binary_deps = check_binary_dependencies(apt_cache, control)
|
|
|
|
|
|
|
|
if unsupported_build_deps or unsupported_binary_deps:
|
2023-01-30 19:45:36 +01:00
|
|
|
print(
|
|
|
|
"\nPlease check https://wiki.ubuntu.com/MainInclusionProcess if "
|
|
|
|
"this source package needs to get into in main/restricted, or "
|
|
|
|
"reconsider if the package really needs above dependencies."
|
|
|
|
)
|
2011-01-14 11:09:21 +01:00
|
|
|
else:
|
2023-01-30 19:45:36 +01:00
|
|
|
print("All dependencies are supported in main or restricted.")
|
2011-01-14 11:09:21 +01:00
|
|
|
|
2017-05-01 00:20:03 +02:00
|
|
|
|
2023-01-30 19:45:36 +01:00
|
|
|
if __name__ == "__main__":
|
2011-01-14 11:09:21 +01:00
|
|
|
main()
|