Check for obsolete or duplicated packages.
-h, --help show this help and exit.
- -m, --mode=MODE chose the MODE to run in (full or daily).
+ -m, --mode=MODE chose the MODE to run in (full, daily, bdo).
-s, --suite=SUITE check suite SUITE.
- -w, --wanna-build-dump where to find the copies of http://buildd.debian.org/stats/*.txt"""
+ -R, --rdep-check check reverse dependencies
+ -w, --wanna-build-dump where to find the copies of https://buildd.debian.org/stats/*.txt"""
sys.exit(exit_code)
################################################################################
version = i[1]
if architectures.has_key(arch):
versions.append(version)
- versions.sort(apt_pkg.VersionCompare)
+ versions.sort(apt_pkg.version_compare)
if versions:
latest_version = versions.pop()
else:
if versions_d != {}:
anais_output += "\n (*) %s_%s [%s]: %s\n" % (binary, latest_version, source, architecture)
versions = versions_d.keys()
- versions.sort(apt_pkg.VersionCompare)
+ versions.sort(apt_pkg.version_compare)
for version in versions:
arches = versions_d[version]
arches.sort()
################################################################################
-def queryWithoutSource(suite_id, session):
- """searches for arch: all packages from suite that do no longer
- reference a source package in the same suite
- subquery unique_binaries: selects all packages with only 1 version
- in suite since 'dak rm' does not allow to specify version numbers"""
-
- query = """
- with unique_binaries as
- (select package, max(version) as version, max(source) as source
- from bin_associations_binaries
- where architecture = 2 and suite = :suite_id
- group by package having count(*) = 1)
- select ub.package, ub.version
- from unique_binaries ub
- left join src_associations_src sas
- on ub.source = sas.src and sas.suite = :suite_id
- where sas.id is null
- order by ub.package"""
- return session.execute(query, { 'suite_id': suite_id })
-
-def reportWithoutSource(suite_name, suite_id, session):
- rows = queryWithoutSource(suite_id, session)
+def reportWithoutSource(suite_name, suite_id, session, rdeps=False):
+ rows = query_without_source(suite_id, session)
title = 'packages without source in suite %s' % suite_name
if rows.rowcount > 0:
print '%s\n%s\n' % (title, '-' * len(title))
print "* package %s in version %s is no longer built from source" % \
(package, version)
print " - suggested command:"
- print " dak rm -m %s -s %s -a all -p -R -b %s\n" % \
+ print " dak rm -m %s -s %s -a all -p -R -b %s" % \
(message, suite_name, package)
+ if rdeps:
+ if utils.check_reverse_depends([package], suite_name, [], session, True):
+ print
+ else:
+ print " - No dependency problem found\n"
+ else:
+ print
def queryNewerAll(suite_name, session):
"""searches for arch != all packages that have an arch == all
print " dak rm -m %s -s %s -a %s -p -b %s\n" % \
(message, suite_name, oldarch, package)
-def queryNBS(suite_id, session):
- """This one is really complex. It searches arch != all packages that
- are no longer built from current source packages in suite.
-
- temp table unique_binaries: will be populated with packages that
- have only one version in suite because 'dak rm' does not allow
- specifying version numbers
-
- temp table newest_binaries: will be populated with packages that are
- built from current sources
- subquery uptodate_arch: returns all architectures built from current
- sources
- subquery unique_binaries_uptodate_arch: returns all packages in
- architectures from uptodate_arch
-
- subquery unique_binaries_uptodate_arch_agg: same as
- unique_binaries_uptodate_arch but with column architecture
- aggregated to array
-
- subquery uptodate_packages: similar to uptodate_arch but returns all
- packages built from current sources
-
- subquery outdated_packages: returns all packages with architectures
- no longer built from current source
- """
-
- query = """
-create temp table unique_binaries (
- package text not null,
- architecture integer not null,
- source integer not null);
-
-insert into unique_binaries
- select bab.package, bab.architecture, max(bab.source)
- from bin_associations_binaries bab
- where bab.suite = :suite_id and bab.architecture > 2
- group by package, architecture having count(*) = 1;
-
-create temp table newest_binaries (
- package text not null,
- architecture integer not null,
- source text not null,
- version debversion not null);
-
-insert into newest_binaries
- select ub.package, ub.architecture, nsa.source, nsa.version
- from unique_binaries ub
- join newest_src_association nsa
- on ub.source = nsa.src and nsa.suite = :suite_id;
-
-with uptodate_arch as
- (select architecture, source, version
- from newest_binaries
- group by architecture, source, version),
- unique_binaries_uptodate_arch as
- (select ub.package, ub.architecture, ua.source, ua.version
- from unique_binaries ub
- join source s
- on ub.source = s.id
- join uptodate_arch ua
- on ub.architecture = ua.architecture and s.source = ua.source),
- unique_binaries_uptodate_arch_agg as
- (select ubua.package,
- array(select unnest(array_agg(a.arch_string)) order by 1) as arch_list,
- ubua.source, ubua.version
- from unique_binaries_uptodate_arch ubua
- join architecture a
- on ubua.architecture = a.id
- group by ubua.source, ubua.version, ubua.package),
- uptodate_packages as
- (select package, source, version
- from newest_binaries
- group by package, source, version),
- outdated_packages as
- (select array(select unnest(array_agg(package)) order by 1) as pkg_list,
- arch_list, source, version
- from unique_binaries_uptodate_arch_agg
- where package not in
- (select package from uptodate_packages)
- group by arch_list, source, version)
- select * from outdated_packages order by source"""
- return session.execute(query, { 'suite_id': suite_id })
-
-def reportNBS(suite_name, suite_id):
+def reportNBS(suite_name, suite_id, rdeps=False):
session = DBConn().session()
nbsRows = queryNBS(suite_id, session)
title = 'NBS packages in suite %s' % suite_name
print " on %s" % arch_string
print " - suggested command:"
message = '"[auto-cruft] NBS (no longer built by %s)"' % source
- print " dak rm -m %s -s %s -a %s -p -R -b %s\n" % \
+ print " dak rm -m %s -s %s -a %s -p -R -b %s" % \
(message, suite_name, arch_string, pkg_string)
+ if rdeps:
+ if utils.check_reverse_depends(pkg_list, suite_name, arch_list, session, True):
+ print
+ else:
+ print " - No dependency problem found\n"
+ else:
+ print
session.close()
-def reportAllNBS(suite_name, suite_id, session):
- reportWithoutSource(suite_name, suite_id, session)
+def reportAllNBS(suite_name, suite_id, session, rdeps=False):
+ reportWithoutSource(suite_name, suite_id, session, rdeps)
reportNewerAll(suite_name, session)
- reportNBS(suite_name, suite_id)
+ reportNBS(suite_name, suite_id, rdeps)
################################################################################
source_binaries.get(source, "(source does not exist)"))
print " won't admit to building:"
versions = dubious_nbs[source].keys()
- versions.sort(apt_pkg.VersionCompare)
+ versions.sort(apt_pkg.version_compare)
for version in versions:
packages = dubious_nbs[source][version].keys()
packages.sort()
LEFT JOIN bin_associations_binaries bab
ON ss.src = bab.source AND ss.suite = bab.suite
WHERE s.suite_name = :suite_name AND bab.id IS NULL
+ AND now() - ss.install_date > '1 day'::interval
ORDER BY install_date"""
args = { 'suite_name': suite_name }
return session.execute(query, args)
################################################################################
+def report_outdated_nonfree(suite, session, rdeps=False):
+
+ packages = {}
+ query = """WITH outdated_sources AS (
+ SELECT s.source, s.version, s.id
+ FROM source s
+ JOIN src_associations sa ON sa.source = s.id
+ WHERE sa.suite IN (
+ SELECT id
+ FROM suite
+ WHERE suite_name = :suite )
+ AND sa.created < (now() - interval :delay)
+ EXCEPT SELECT s.source, max(s.version) AS version, max(s.id)
+ FROM source s
+ JOIN src_associations sa ON sa.source = s.id
+ WHERE sa.suite IN (
+ SELECT id
+ FROM suite
+ WHERE suite_name = :suite )
+ AND sa.created < (now() - interval :delay)
+ GROUP BY s.source ),
+ binaries AS (
+ SELECT b.package, s.source, (
+ SELECT a.arch_string
+ FROM architecture a
+ WHERE a.id = b.architecture ) AS arch
+ FROM binaries b
+ JOIN outdated_sources s ON s.id = b.source
+ JOIN bin_associations ba ON ba.bin = b.id
+ JOIN override o ON o.package = b.package AND o.suite = ba.suite
+ WHERE ba.suite IN (
+ SELECT id
+ FROM suite
+ WHERE suite_name = :suite )
+ AND o.component IN (
+ SELECT id
+ FROM component
+ WHERE name = 'non-free' ) )
+ SELECT DISTINCT package, source, arch
+ FROM binaries
+ ORDER BY source, package, arch"""
+
+ res = session.execute(query, {'suite': suite, 'delay': "'15 days'"})
+ for package in res:
+ binary = package[0]
+ source = package[1]
+ arch = package[2]
+ if arch == 'all':
+ continue
+ if not source in packages:
+ packages[source] = {}
+ if not binary in packages[source]:
+ packages[source][binary] = set()
+ packages[source][binary].add(arch)
+ if packages:
+ title = 'Outdated non-free binaries in suite %s' % suite
+ message = '"[auto-cruft] outdated non-free binaries"'
+ print '%s\n%s\n' % (title, '-' * len(title))
+ for source in sorted(packages):
+ archs = set()
+ binaries = set()
+ print '* package %s has outdated non-free binaries' % source
+ print ' - suggested command:'
+ for binary in sorted(packages[source]):
+ binaries.add(binary)
+ archs = archs.union(packages[source][binary])
+ print ' dak rm -m %s -s %s -a %s -p -R -b %s' % \
+ (message, suite, ','.join(archs), ' '.join(binaries))
+ if rdeps:
+ if utils.check_reverse_depends(list(binaries), suite, archs, session, True):
+ print
+ else:
+ print " - No dependency problem found\n"
+ else:
+ print
+
+################################################################################
+
def main ():
global suite, suite_id, source_binaries, source_versions
Arguments = [('h',"help","Cruft-Report::Options::Help"),
('m',"mode","Cruft-Report::Options::Mode", "HasArg"),
+ ('R',"rdep-check", "Cruft-Report::Options::Rdep-Check"),
('s',"suite","Cruft-Report::Options::Suite","HasArg"),
('w',"wanna-build-dump","Cruft-Report::Options::Wanna-Build-Dump","HasArg")]
- for i in [ "help" ]:
+ for i in [ "help", "Rdep-Check" ]:
if not cnf.has_key("Cruft-Report::Options::%s" % (i)):
cnf["Cruft-Report::Options::%s" % (i)] = ""
if not cnf.has_key("Cruft-Report::Options::Wanna-Build-Dump"):
cnf["Cruft-Report::Options::Wanna-Build-Dump"] = "/srv/ftp-master.debian.org/scripts/nfu"
- apt_pkg.ParseCommandLine(cnf.Cnf, Arguments, sys.argv)
+ apt_pkg.parse_commandline(cnf.Cnf, Arguments, sys.argv)
- Options = cnf.SubTree("Cruft-Report::Options")
+ Options = cnf.subtree("Cruft-Report::Options")
if Options["Help"]:
usage()
+ if Options["Rdep-Check"]:
+ rdeps = True
+ else:
+ rdeps = False
+
# Set up checks based on mode
if Options["Mode"] == "daily":
- checks = [ "nbs", "nviu", "nvit", "obsolete source", "nfu" ]
+ checks = [ "nbs", "nviu", "nvit", "obsolete source", "outdated non-free", "nfu" ]
elif Options["Mode"] == "full":
- checks = [ "nbs", "nviu", "nvit", "obsolete source", "nfu", "dubious nbs", "bnb", "bms", "anais" ]
+ checks = [ "nbs", "nviu", "nvit", "obsolete source", "outdated non-free", "nfu", "dubious nbs", "bnb", "bms", "anais" ]
+ elif Options["Mode"] == "bdo":
+ checks = [ "nbs", "obsolete source" ]
else:
- utils.warn("%s is not a recognised mode - only 'full' or 'daily' are understood." % (Options["Mode"]))
+ utils.warn("%s is not a recognised mode - only 'full', 'daily' or 'bdo' are understood." % (Options["Mode"]))
usage(1)
session = DBConn().session()
nfu_packages = {}
suite = get_suite(Options["Suite"].lower(), session)
+ if not suite:
+ utils.fubar("Cannot find suite %s" % Options["Suite"].lower())
+
suite_id = suite.suite_id
suite_name = suite.suite_name.lower()
report_obsolete_source(suite_name, session)
if "nbs" in checks:
- reportAllNBS(suite_name, suite_id, session)
+ reportAllNBS(suite_name, suite_id, session, rdeps)
+
+ if "outdated non-free" in checks:
+ report_outdated_nonfree(suite_name, session, rdeps)
bin_not_built = {}
bins_in_suite = get_suite_binaries(suite, session)
# Checks based on the Sources files
- components = cnf.ValueList("Suite::%s::Components" % (suite_name))
+ components = get_component_names(session)
for component in components:
- filename = "%s/dists/%s/%s/source/Sources.gz" % (cnf["Dir::Root"], suite_name, component)
- # apt_pkg.ParseTagFile needs a real file handle and can't handle a GzipFile instance...
+ filename = "%s/dists/%s/%s/source/Sources.gz" % (suite.archive.path, suite_name, component)
+ # apt_pkg.TagFile needs a real file handle and can't handle a GzipFile instance...
(fd, temp_filename) = utils.temp_filename()
(result, output) = commands.getstatusoutput("gunzip -c %s > %s" % (filename, temp_filename))
if (result != 0):
sys.stderr.write("Gunzip invocation failed!\n%s\n" % (output))
sys.exit(result)
sources = utils.open_file(temp_filename)
- Sources = apt_pkg.ParseTagFile(sources)
- while Sources.Step():
- source = Sources.Section.Find('Package')
- source_version = Sources.Section.Find('Version')
- architecture = Sources.Section.Find('Architecture')
- binaries = Sources.Section.Find('Binary')
+ Sources = apt_pkg.TagFile(sources)
+ while Sources.step():
+ source = Sources.section.find('Package')
+ source_version = Sources.section.find('Version')
+ architecture = Sources.section.find('Architecture')
+ binaries = Sources.section.find('Binary')
binaries_list = [ i.strip() for i in binaries.split(',') ]
if "bnb" in checks:
for architecture in architectures:
if component == 'main/debian-installer' and re.match("kfreebsd", architecture):
continue
- filename = "%s/dists/%s/%s/binary-%s/Packages.gz" % (cnf["Dir::Root"], suite_name, component, architecture)
- # apt_pkg.ParseTagFile needs a real file handle
+ filename = "%s/dists/%s/%s/binary-%s/Packages.gz" % (suite.archive.path, suite_name, component, architecture)
+ # apt_pkg.TagFile needs a real file handle
(fd, temp_filename) = utils.temp_filename()
(result, output) = commands.getstatusoutput("gunzip -c %s > %s" % (filename, temp_filename))
if (result != 0):
nfu_entries = parse_nfu(architecture)
packages = utils.open_file(temp_filename)
- Packages = apt_pkg.ParseTagFile(packages)
- while Packages.Step():
- package = Packages.Section.Find('Package')
- source = Packages.Section.Find('Source', "")
- version = Packages.Section.Find('Version')
+ Packages = apt_pkg.TagFile(packages)
+ while Packages.step():
+ package = Packages.section.find('Package')
+ source = Packages.section.find('Source', "")
+ version = Packages.section.find('Version')
if source == "":
source = package
if bin2source.has_key(package) and \
- apt_pkg.VersionCompare(version, bin2source[package]["version"]) > 0:
+ apt_pkg.version_compare(version, bin2source[package]["version"]) > 0:
bin2source[package]["version"] = version
bin2source[package]["source"] = source
else:
for source in nbs.keys():
for package in nbs[source].keys():
versions = nbs[source][package].keys()
- versions.sort(apt_pkg.VersionCompare)
+ versions.sort(apt_pkg.version_compare)
latest_version = versions.pop()
source_version = source_versions.get(source,"0")
- if apt_pkg.VersionCompare(latest_version, source_version) == 0:
+ if apt_pkg.version_compare(latest_version, source_version) == 0:
add_nbs(dubious_nbs, source, latest_version, package, suite_id, session)
if "nviu" in checks: