~brian-murray/ubuntu-archive-tools/pu-no-email

« back to all changes in this revision

Viewing changes to orphaned-sources

  • Committer: Colin Watson
  • Date: 2013-04-24 08:46:17 UTC
  • Revision ID: cjwatson@canonical.com-20130424084617-mfgezo4okfnhaxy4
orphaned-source: new script

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/python
 
2
 
 
3
from __future__ import print_function
 
4
 
 
5
import atexit
 
6
import bz2
 
7
from contextlib import closing
 
8
from optparse import OptionParser
 
9
import shutil
 
10
import sys
 
11
import tempfile
 
12
try:
 
13
    from urllib.request import urlretrieve
 
14
except ImportError:
 
15
    from urllib import urlretrieve
 
16
 
 
17
import apt_pkg
 
18
from launchpadlib.launchpad import Launchpad
 
19
 
 
20
import lputils
 
21
 
 
22
 
 
23
tempdir = None
 
24
 
 
25
 
 
26
def ensure_tempdir():
 
27
    global tempdir
 
28
    if not tempdir:
 
29
        tempdir = tempfile.mkdtemp(prefix="orphaned-sources")
 
30
        atexit.register(shutil.rmtree, tempdir)
 
31
 
 
32
 
 
33
def decompress_open(tagfile):
 
34
    if tagfile.startswith("http:") or tagfile.startswith("ftp:"):
 
35
        url = tagfile
 
36
        tagfile = urlretrieve(url)[0]
 
37
 
 
38
    if tagfile.endswith(".bz2"):
 
39
        ensure_tempdir()
 
40
        decompressed = tempfile.mktemp(dir=tempdir)
 
41
        with closing(bz2.BZ2File(tagfile)) as fin:
 
42
            with open(decompressed, "wb") as fout:
 
43
                fout.write(fin.read())
 
44
        return open(decompressed, "r")
 
45
    else:
 
46
        return open(tagfile, "r")
 
47
 
 
48
 
 
49
def archive_base(archtag):
 
50
    if archtag in ("amd64", "i386", "src"):
 
51
        return "http://archive.ubuntu.com/ubuntu"
 
52
    else:
 
53
        return "http://ports.ubuntu.com/ubuntu-ports"
 
54
 
 
55
 
 
56
def source_names(options):
 
57
    sources = set()
 
58
    for component in "main", "restricted", "universe", "multiverse":
 
59
        url = "%s/dists/%s/%s/source/Sources.bz2" % (
 
60
            archive_base("src"), options.suite, component)
 
61
        print("Reading %s ..." % url, file=sys.stderr)
 
62
        for section in apt_pkg.TagFile(decompress_open(url)):
 
63
            sources.add(section["Package"])
 
64
    return sources
 
65
 
 
66
 
 
67
def referenced_sources(options):
 
68
    sources = set()
 
69
    for component in "main", "restricted", "universe", "multiverse":
 
70
        for arch in options.architectures:
 
71
            archtag = arch.architecture_tag
 
72
            for suffix in "", "/debian-installer":
 
73
                url = "%s/dists/%s/%s%s/binary-%s/Packages.bz2" % (
 
74
                    archive_base(archtag), options.suite, component, suffix,
 
75
                    archtag)
 
76
                print("Reading %s ..." % url, file=sys.stderr)
 
77
                for section in apt_pkg.TagFile(decompress_open(url)):
 
78
                    if "Source" in section:
 
79
                        sources.add(section["Source"].split(" ", 1)[0])
 
80
                    else:
 
81
                        sources.add(section["Package"])
 
82
    return sources
 
83
 
 
84
 
 
85
def main():
 
86
    parser = OptionParser(
 
87
        description="Check for sources without any remaining binaries.")
 
88
    parser.add_option(
 
89
        "-l", "--launchpad", dest="launchpad_instance", default="production")
 
90
    parser.add_option("-s", "--suite", help="check this suite")
 
91
    options, _ = parser.parse_args()
 
92
 
 
93
    options.distribution = "ubuntu"
 
94
    options.launchpad = Launchpad.login_anonymously(
 
95
        "orphaned-sources", options.launchpad_instance)
 
96
    lputils.setup_location(options)
 
97
 
 
98
    if options.pocket != "Release":
 
99
        parser.error("cannot run on non-release pocket")
 
100
 
 
101
    orphaned_sources = source_names(options) - referenced_sources(options)
 
102
    for source in sorted(orphaned_sources):
 
103
        print(source)
 
104
 
 
105
 
 
106
if __name__ == '__main__':
 
107
    main()