You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

166 lines
5.2 KiB

#! /usr/bin/python2.7
from __future__ import print_function
import atexit
import bz2
from collections import defaultdict
import json
import lzma
from optparse import OptionParser
import requests
import shutil
import sys
import tempfile
import apt_pkg
from launchpadlib.launchpad import Launchpad
import lputils
tempdir = None
def ensure_tempdir():
global tempdir
if not tempdir:
tempdir = tempfile.mkdtemp(prefix="unsubscribed-packages")
atexit.register(shutil.rmtree, tempdir)
def decompress_open(tagfile):
if tagfile.startswith("http:") or tagfile.startswith("ftp:"):
url = tagfile
tagfile = requests.get(url)
if tagfile.status_code == 404:
url = url.replace(".xz", ".bz2")
tagfile = requests.get(url)
ensure_tempdir()
decompressed = tempfile.mktemp(dir=tempdir)
with open(decompressed, "wb") as fout:
if url.endswith(".xz"):
fout.write(lzma.decompress(tagfile.content))
elif url.endswith(".bz2"):
fout.write(bz2.decompress(tagfile.content))
return open(decompressed, "r")
def archive_base(archtag):
if archtag in ("amd64", "i386", "src"):
return "http://archive.ubuntu.com/ubuntu"
else:
return "http://ports.ubuntu.com/ubuntu-ports"
def source_names(options):
sources = dict()
for suite in options.suites:
for component in ["main", "restricted"]:
url = "%s/dists/%s/%s/source/Sources.xz" % (
archive_base("src"), suite, component)
if not options.quiet:
print("Reading %s ..." % url, file=sys.stderr)
for section in apt_pkg.TagFile(decompress_open(url)):
pkg = section["Package"]
if suite == options.dev_suite:
sources[pkg] = True
else:
if sources.get(pkg, False) == True:
continue
sources[pkg] = False
return sources
def main():
parser = OptionParser(
description="Check for source packages in main or restricted in "
"active distro series and return a json file of the teams "
"to which they map.")
parser.add_option(
"-l", "--launchpad", dest="launchpad_instance", default="production")
parser.add_option(
"-u", "--unsubscribed", action="store_true", default=False,
help="Only return packages which have no subscriber")
parser.add_option(
"-p", "--print", action="store_true", default=False,
dest="display",
help="Print results to screen instead of a json file")
parser.add_option(
"-o", "--output-file", default="package-team-mapping.json",
help="output JSON to this file")
parser.add_option(
"-q", "--quiet", action="store_true", default=False,
help="Quieten progress messages")
options, _ = parser.parse_args()
options.suite = None
options.distribution = "ubuntu"
options.launchpad = Launchpad.login_with(
"unsubscribed-packages", options.launchpad_instance)
launchpad = options.launchpad
ubuntu = launchpad.distributions[options.distribution]
options.suites = []
for series in ubuntu.series:
# very few lucid packages are supported
if series.name == 'lucid':
continue
if series.active:
options.suites.append(series.name)
# find the dev series
if series.status in ['Active Development', 'Pre-release Freeze']:
options.dev_suite = series.name
lputils.setup_location(options)
team_names = [
'checkbox-bugs',
'desktop-packages',
'documentation-packages',
'foundations-bugs',
'kernel-packages',
'kubuntu-bugs',
'landscape',
'maas-maintainers',
'mir-team',
'pkg-ime',
'snappy-dev',
'translators-packages',
'ubuntu-openstack',
'ubuntu-printing',
'ubuntu-security',
'ubuntu-server',
]
data = { "unsubscribed": [] }
subscriptions = defaultdict(list)
for team_name in team_names:
data[team_name] = []
team = launchpad.people[team_name]
team_subs = team.getBugSubscriberPackages()
for src_pkg in team_subs:
subscriptions[src_pkg.name].append(team_name)
data[team_name].append(src_pkg.name)
source_packages = source_names(options)
for source_package in sorted(source_packages):
# we only care about ones people are not subscribed to in the dev release
if source_package not in subscriptions and source_packages[source_package]:
data["unsubscribed"].append(source_package)
if options.display:
print("No team is subscribed to: %s" %
source_package)
else:
if not options.unsubscribed:
if options.display:
print("%s is subscribed to: %s" %
(team_name, source_package))
if not options.display:
with open(options.output_file, 'w') as json_file:
json_file.write(json.dumps(data, indent=4))
if __name__ == '__main__':
main()