Refactoring; Implementing file_conflicts and provides_conflicts reports

This commit is contained in:
Alexander Lakhin 2014-02-14 15:40:49 +04:00
parent fc2df4ccb5
commit 6bdb49da9d
5 changed files with 507 additions and 375 deletions

View file

@ -9,7 +9,7 @@ import string
import rpm import rpm
import re import re
import gettext import gettext
from versutils import * prepare_repodb = __import__("prepare-repodb")
gettext.install('urpm-tools') gettext.install('urpm-tools')
@ -72,9 +72,9 @@ SELECT id, nvra, version, release FROM packages WHERE repodir_id IN (%s) AND nam
verrel = (vpid[2] if vpid[2] is not None else '') + '-' + \ verrel = (vpid[2] if vpid[2] is not None else '') + '-' + \
(vpid[3] if vpid[3] is not None else '') (vpid[3] if vpid[3] is not None else '')
if not better_found: if not better_found:
better_found = version_ok(chosen_version, better_found = prepare_repodb.version_ok(chosen_version,
RPMSENSE_GREATER, RPMSENSE_GREATER,
verrel) verrel)
if better_found: if better_found:
pid = vpid[0] pid = vpid[0]
chosen_nvra = vpid[1] chosen_nvra = vpid[1]
@ -91,9 +91,9 @@ SELECT id, nvra, version, release FROM packages WHERE repodir_id IN (%s) AND nam
in_packages = ','.join(str(id) for id in package_ids) in_packages = ','.join(str(id) for id in package_ids)
for required_package in c.execute(""" for required_package in c.execute("""
SELECT packages.id, packages.name, nvra SELECT packages.id, packages.name, nvra
FROM packages, package_depend_res FROM packages, package_requires_res
WHERE packages.id = package_depend_res.dep_package_id AND WHERE packages.id = package_requires_res.dep_package_id AND
package_depend_res.package_id IN (%s) AND package_requires_res.package_id IN (%s) AND
packages.repodir_id IN (%s) AND packages.repodir_id IN (%s) AND
packages.id NOT IN (%s) packages.id NOT IN (%s)
ORDER BY packages.name ORDER BY packages.name

View file

@ -64,10 +64,10 @@ SELECT packages.id, nvra, repodir_id, repodirs.name,
rpm_requires.name AS req_name, rpm_requires.build_arch AS req_arch rpm_requires.name AS req_name, rpm_requires.build_arch AS req_arch
FROM packages, repodirs, rpm_requires FROM packages, repodirs, rpm_requires
WHERE packages.repodir_id = repodirs.id AND WHERE packages.repodir_id = repodirs.id AND
packages.id=rpm_requires.package_id AND packages.id = rpm_requires.package_id AND
NOT EXISTS (SELECT 1 FROM package_depend_res pdr NOT EXISTS (SELECT 1 FROM package_requires_res pqr
WHERE pdr.package_id = packages.id AND WHERE pqr.package_id = packages.id AND
pdr.requires_id = rpm_requires.id) pqr.requires_id = rpm_requires.id)
ORDER BY repodir_id, nvra""").fetchall() ORDER BY repodir_id, nvra""").fetchall()
all_broken = {} all_broken = {}
@ -118,11 +118,11 @@ SELECT packages.id, nvra, repodir_id, repodirs.name,
packages_broken_recurs = dbc.execute(""" packages_broken_recurs = dbc.execute("""
SELECT packages.id, nvra, repodir_id, repodirs.name, SELECT packages.id, nvra, repodir_id, repodirs.name,
rpm_requires.name AS req_name, build_arch, dep_package_id rpm_requires.name AS req_name, build_arch, dep_package_id
FROM packages, repodirs, rpm_requires, package_depend_res FROM packages, repodirs, rpm_requires, package_requires_res
WHERE packages.repodir_id = repodirs.id AND WHERE packages.repodir_id = repodirs.id AND
packages.id = rpm_requires.package_id AND packages.id = rpm_requires.package_id AND
packages.id = package_depend_res.package_id AND packages.id = package_requires_res.package_id AND
rpm_requires.id = package_depend_res.requires_id AND rpm_requires.id = package_requires_res.requires_id AND
dep_package_id IN (%(pids)s) AND dep_package_id IN (%(pids)s) AND
packages.id NOT IN (%(pids)s) packages.id NOT IN (%(pids)s)
ORDER BY repodir_id, nvra""" % {'pids': pids}).fetchall() ORDER BY repodir_id, nvra""" % {'pids': pids}).fetchall()
@ -143,7 +143,7 @@ SELECT id, name, sources FROM repodirs ORDER BY id""").fetchall()
reponames = {repodir[0]: repodir[1] for repodir in all_repodirs} reponames = {repodir[0]: repodir[1] for repodir in all_repodirs}
if broken_recursive: if broken_recursive:
print 'Recursive broken dependencies:' print '===\nRecursive broken dependencies:'
for rd in all_repodirs: for rd in all_repodirs:
(rd_id, rd_name, rd_sources) = (rd[0], rd[1], rd[2]) (rd_id, rd_name, rd_sources) = (rd[0], rd[1], rd[2])
if rd_sources == '.': if rd_sources == '.':
@ -223,9 +223,9 @@ SELECT id, name, sources, path FROM repodirs ORDER BY id
(rd_id, rd_name) = (repodir[0], repodir[1]) (rd_id, rd_name) = (repodir[0], repodir[1])
loopbacks = dbc.execute(""" loopbacks = dbc.execute("""
SELECT p.id, p.nvra, rpm_requires.name SELECT p.id, p.nvra, rpm_requires.name
FROM package_depend_res pdr, packages p, rpm_requires FROM package_requires_res pqr, packages p, rpm_requires
WHERE pdr.package_id = p.id AND pdr.package_id = dep_package_id AND WHERE pqr.package_id = p.id AND pqr.package_id = dep_package_id AND
rpm_requires.id = pdr.requires_id and p.repodir_id = ? rpm_requires.id = pqr.requires_id and p.repodir_id = ?
ORDER BY p.nvra, rpm_requires.name ORDER BY p.nvra, rpm_requires.name
""", [rd_id]).fetchall() """, [rd_id]).fetchall()
if loopbacks: if loopbacks:
@ -253,27 +253,6 @@ SELECT p.id, p.nvra, rpm_requires.name
print 'Total: %d' % cnt print 'Total: %d' % cnt
def detect_lost_sources(dbc):
print '==='
print 'Lost sources:'
repodirs = dbc.execute("""
SELECT id, name, sources, path FROM repodirs WHERE sources <> '.' ORDER BY id
""").fetchall()
for repodir in repodirs:
(rd_id, rd_name) = (repodir[0], repodir[1])
lost_sources = dbc.execute("""
SELECT name, nvra, sourcerpm FROM packages
WHERE repodir_id = ? AND
sourcerpm IS NOT NULL AND sourcerpm_package IS NULL
ORDER BY name
""", [rd_id]).fetchall()
if lost_sources:
print '%d) %s' % (rd_id, rd_name)
for ls in lost_sources:
print '\t%s (%s)' % (ls[1], ls[2])
print 'Total: %d' % len(lost_sources)
def analyze_partitioning(dbc): def analyze_partitioning(dbc):
print '===' print '==='
print 'Possible partitioning:' print 'Possible partitioning:'
@ -310,20 +289,20 @@ SELECT id, name, nvra
part_packages = ','.join(str(id) for id in partition_ids) part_packages = ','.join(str(id) for id in partition_ids)
upper_packages = dbc.execute(""" upper_packages = dbc.execute("""
SELECT packages.id, packages.name, nvra SELECT packages.id, packages.name, nvra
FROM packages, package_depend_res FROM packages, package_requires_res
WHERE packages.id = package_depend_res.package_id AND WHERE packages.id = package_requires_res.package_id AND
packages.repodir_id = ? AND packages.repodir_id = ? AND
package_depend_res.dep_package_id IN (%s) AND package_requires_res.dep_package_id IN (%s) AND
packages.id NOT IN (%s) packages.id NOT IN (%s)
ORDER BY packages.name ORDER BY packages.name
""" % (cl_packages, part_packages), [rd_id]).fetchall() """ % (cl_packages, part_packages), [rd_id]).fetchall()
lower_packages = dbc.execute(""" lower_packages = dbc.execute("""
SELECT packages.id, packages.name, nvra SELECT packages.id, packages.name, nvra
FROM packages, package_depend_res FROM packages, package_requires_res
WHERE packages.id = package_depend_res.dep_package_id AND WHERE packages.id = package_requires_res.dep_package_id AND
packages.repodir_id = ? AND packages.repodir_id = ? AND
package_depend_res.package_id IN (%s) AND package_requires_res.package_id IN (%s) AND
packages.id NOT IN (%s) packages.id NOT IN (%s)
ORDER BY packages.name ORDER BY packages.name
""" % (cl_packages, part_packages), [rd_id]).fetchall() """ % (cl_packages, part_packages), [rd_id]).fetchall()
@ -361,161 +340,256 @@ SELECT packages.id, packages.name, nvra
print '\t%s' % s print '\t%s' % s
print 'Total: %d' % len(singles) print 'Total: %d' % len(singles)
def detect_lost_object_files(dbc): class query_output:
header = '===\n' \ repositories = {}
'Lost object (executable) files (provided but not found):' repodirs = None
repodirs = dbc.execute(""" title = None
dbc = None
def __init__(self, dbc):
self.dbc = dbc
self.repodirs = dbc.execute("""
SELECT id, name, sources, path FROM repodirs ORDER BY id SELECT id, name, sources, path FROM repodirs ORDER BY id
""").fetchall() """).fetchall()
for repodir in repodirs: for repodir in self.repodirs:
(rd_id, rd_name) = (repodir[0], repodir[1]) (rd_id, rd_name) = (repodir[0], repodir[1])
lost_object_files = dbc.execute(""" (output, count) = self.get_data(rd_id)
SELECT nvra, package_files.path, mark repo_out_dict = {'output': output, 'count': count}
self.repositories[rd_id] = repo_out_dict
def get_repodir_name(self, repodir_id):
for repodir in self.repodirs:
if repodir[0] == repodir_id:
return repodir[1]
return None
def print_text(self):
title_printed = False
for repodir in self.repodirs:
(rd_id, rd_name) = (repodir[0], repodir[1])
if rd_id not in self.repositories:
continue
repodir = self.repositories[rd_id]
repo_output = repodir['output']
if repo_output is None or len(repo_output) > 0:
if self.title and not title_printed:
print '===\n' + self.title + ':'
title_printed = True
self.print_text_reponame(rd_id, rd_name)
if repo_output is not None:
for line in repo_output:
print '\t' + line
print 'Total: %d' % repodir['count']
def print_text_reponame(self, repodir_id, repodir_name):
print '%d) %s' % (repodir_id, repodir_name)
def get_data(self, repodir_id):
return (None, 0)
class query_output_rows(query_output):
query = ''
def get_data(self, repodir_id):
rows = self.dbc.execute(self.query, [repodir_id]).fetchall()
result = [row[0] for row in rows]
return (result, len(rows))
class query_output_count(query_output):
query = None
def get_data(self, repodir_id):
count_rec = self.dbc.execute(self.query, [repodir_id]).fetchone()
return (None, count_rec[0])
def print_text_reponame(self, repodir_id, repodir_name):
print '%d) %s: %d' % (repodir_id, repodir_name,
self.repositories[repodir_id]['count'])
class lost_sources(query_output_rows):
title = 'Lost sources'
query = """
SELECT nvra || ' (' || sourcerpm || ')' FROM packages
WHERE repodir_id = ? AND
sourcerpm IS NOT NULL AND sourcerpm_package IS NULL
ORDER BY name
"""
class lost_object_files(query_output_rows):
title = 'Lost object (executable) files (provided but not found)'
query = """
SELECT nvra || ': ' || package_files.path
FROM packages, package_files FROM packages, package_files
WHERE repodir_id = ? AND packages.id = package_files.package_id AND mark = 'not-found' WHERE repodir_id = ? AND packages.id = package_files.package_id AND mark = 'not-found'
ORDER BY packages.name, package_files.path ORDER BY packages.name, package_files.path
""", [rd_id]).fetchall() """
if lost_object_files:
if header:
print header
header = None
print '%d) %s' % (rd_id, rd_name)
for lof in lost_object_files:
print '\t%s: %s' % (lof[0], lof[1])
print 'Total: %d' % len(lost_object_files)
def detect_broken_object_links(dbc): class broken_object_links(query_output_rows):
header = '===\n' \ title = 'Invalid object (executable) file links'
'Invalid object (executable) file links:' query = """
repodirs = dbc.execute(""" SELECT nvra || ': ' || package_files.path || ' -/-> ' || link_to_path
SELECT id, name, sources, path FROM repodirs ORDER BY id
""").fetchall()
for repodir in repodirs:
(rd_id, rd_name) = (repodir[0], repodir[1])
broken_object_links = dbc.execute("""
SELECT nvra, package_files.path, link_to_path, mark
FROM packages, package_files FROM packages, package_files
WHERE repodir_id = ? AND packages.id = package_files.package_id AND WHERE repodir_id = ? AND packages.id = package_files.package_id AND
mark = 'link' AND link_to_path IS NOT NULL AND link_to_file_id IS NULL mark = 'link' AND link_to_path IS NOT NULL AND link_to_file_id IS NULL
ORDER BY packages.name, package_files.path ORDER BY packages.name, package_files.path
""", [rd_id]).fetchall() """
if broken_object_links:
if header:
print header
header = None
print '%d) %s' % (rd_id, rd_name)
for bol in broken_object_links:
print '\t%s: %s -/-> %s' % \
(bol[0], bol[1], bol[2])
print 'Total: %d' % len(broken_object_links)
def get_repodir_depends(dbc, repodir_id): def print_reponame_with_depends(dbc, repodir_id, repodir_name):
dep_repos = dbc.execute(""" dep_repos = dbc.execute("""
SELECT depend_repodir_name FROM repodir_depends WHERE repodir_id = ? SELECT depend_repodir_name FROM repodir_depends WHERE repodir_id = ?
""", [repodir_id]).fetchall() """, [repodir_id]).fetchall()
return ', '.join([dep_repo[0] for dep_repo in dep_repos]) repodir_depends = ', '.join([dep_repo[0] for dep_repo in dep_repos])
print ('%d) %s' % (repodir_id, repodir_name)) + \
('' if repodir_depends == '' else
(' (depends on: %s)' % repodir_depends))
def detect_so_needed_not_resolved(dbc):
repodirs = dbc.execute(""" class so_needed_resolved1(query_output_count):
SELECT id, name, sources, path FROM repodirs ORDER BY id title = 'Objects needed and resolved by rpm requires-provides'
""").fetchall() query = """
print '==='
print 'Objects needed and resolved by rpm requires-provides:'
for repodir in repodirs:
(rd_id, rd_name) = (repodir[0], repodir[1])
objects_needed_resolved1 = dbc.execute("""
SELECT COUNT(1) FROM packages CROSS JOIN package_files CROSS JOIN so_needed CROSS JOIN so_needed_res SELECT COUNT(1) FROM packages CROSS JOIN package_files CROSS JOIN so_needed CROSS JOIN so_needed_res
WHERE repodir_id = ? AND package_files.package_id = packages.id AND WHERE repodir_id = ? AND package_files.package_id = packages.id AND
so_needed.obj_file_id = package_files.id AND so_needed_id = so_needed.id AND res_type = 1 so_needed.obj_file_id = package_files.id AND so_needed_id = so_needed.id AND res_type = 1
""", [rd_id]).fetchone() """
print '%d) %s: %d' % (rd_id, rd_name, objects_needed_resolved1[0])
print '===' class so_needed_resolved2(query_output_count):
print 'Objects needed and resolved by flat search:' title = 'Objects needed and resolved by flat search'
for repodir in repodirs: query = """
(rd_id, rd_name) = (repodir[0], repodir[1])
objects_needed_resolved2 = dbc.execute("""
SELECT COUNT(1) FROM packages CROSS JOIN package_files CROSS JOIN so_needed CROSS JOIN so_needed_res SELECT COUNT(1) FROM packages CROSS JOIN package_files CROSS JOIN so_needed CROSS JOIN so_needed_res
WHERE repodir_id = ? AND package_files.package_id = packages.id AND WHERE repodir_id = ? AND package_files.package_id = packages.id AND
so_needed.obj_file_id = package_files.id AND so_needed_id = so_needed.id AND res_type = 2 so_needed.obj_file_id = package_files.id AND so_needed_id = so_needed.id AND res_type = 2
""", [rd_id]).fetchone() """
print '%d) %s: %d' % (rd_id, rd_name, objects_needed_resolved2[0])
header = '===' \ class so_needed_not_resolved(query_output_rows):
'Objects needed but not resolved:' title = 'Objects needed but not resolved'
for repodir in repodirs: query = """
(rd_id, rd_name) = (repodir[0], repodir[1]) SELECT packages.nvra || ': ' || package_files.path || ' -?-> ' || so_needed.name
objects_needed_not_resolved = dbc.execute("""
SELECT packages.nvra, package_files.path, so_needed.name
FROM packages CROSS JOIN package_files CROSS JOIN so_needed FROM packages CROSS JOIN package_files CROSS JOIN so_needed
LEFT OUTER JOIN so_needed_res ON so_needed_id = so_needed.id LEFT OUTER JOIN so_needed_res ON so_needed_id = so_needed.id
WHERE repodir_id = ? AND package_files.package_id = packages.id AND WHERE repodir_id = ? AND package_files.package_id = packages.id AND
so_needed.obj_file_id = package_files.id AND so_needed_id IS NULL so_needed.obj_file_id = package_files.id AND so_needed_id IS NULL
""", [rd_id]).fetchall() """
if objects_needed_not_resolved: def print_reponame(self, repodir_id, repodir_name):
repodir_depends = get_repodir_depends(dbc, rd_id) print_reponame_with_depends(self.dbc, repodir_id, repodir_name)
if header:
print header
header = None
print ('%d) %s' % (rd_id, rd_name)) + \
('' if repodir_depends == '' else
(' (depends on: %s)' % repodir_depends))
for obj_nr in objects_needed_not_resolved:
print '\t%s: %s -?-> %s' % (obj_nr[0], obj_nr[1], obj_nr[2])
print 'Total: %d' % len(objects_needed_not_resolved)
def detect_symbols_not_resolved(dbc): class symbols_resolved1_2(query_output_count):
repodirs = dbc.execute(""" title = 'Symbols resolved by .so NEEDED search'
SELECT id, name, sources, path FROM repodirs ORDER BY id query = """
""").fetchall()
print '==='
print 'Symbols resolved by .so NEEDED search:'
for repodir in repodirs:
(rd_id, rd_name) = (repodir[0], repodir[1])
symbols_resolved1_2 = dbc.execute("""
SELECT COUNT(1) FROM packages CROSS JOIN package_files CROSS JOIN obj_symbols CROSS JOIN obj_symbols_res SELECT COUNT(1) FROM packages CROSS JOIN package_files CROSS JOIN obj_symbols CROSS JOIN obj_symbols_res
WHERE packages.repodir_id = ? AND packages.id = package_files.package_id AND WHERE packages.repodir_id = ? AND packages.id = package_files.package_id AND
package_files.id = obj_symbols.obj_file_id AND sym_type = 0 AND package_files.id = obj_symbols.obj_file_id AND sym_type = 0 AND
obj_symbols_res.obj_sym_id = obj_symbols.id AND res_type IN (1, 2) obj_symbols_res.obj_sym_id = obj_symbols.id AND res_type IN (1, 2)
""", [rd_id]).fetchone() """
print '%d) %s: %d' % (rd_id, rd_name, symbols_resolved1_2[0])
class symbols_resolved3(query_output_count):
print '===' title = 'Symbols resolved by flat search'
print 'Symbols resolved by flat search:' query = """
for repodir in repodirs:
(rd_id, rd_name) = (repodir[0], repodir[1])
symbols_resolved3 = dbc.execute("""
SELECT COUNT(1) FROM packages CROSS JOIN package_files CROSS JOIN obj_symbols CROSS JOIN obj_symbols_res SELECT COUNT(1) FROM packages CROSS JOIN package_files CROSS JOIN obj_symbols CROSS JOIN obj_symbols_res
WHERE packages.repodir_id = ? AND packages.id = package_files.package_id AND WHERE packages.repodir_id = ? AND packages.id = package_files.package_id AND
package_files.id = obj_symbols.obj_file_id AND sym_type = 0 AND package_files.id = obj_symbols.obj_file_id AND sym_type = 0 AND
obj_symbols_res.obj_sym_id = obj_symbols.id AND res_type = 3 obj_symbols_res.obj_sym_id = obj_symbols.id AND res_type = 3
""", [rd_id]).fetchone() """
print '%d) %s: %d' % (rd_id, rd_name, symbols_resolved3[0])
header = '===' \ class symbols_not_resolved(query_output_rows):
'Symbols not resolved:' title = 'Symbols not resolved'
for repodir in repodirs: query = """
(rd_id, rd_name) = (repodir[0], repodir[1]) SELECT packages.nvra || ': ' || package_files.path || ' -?-> ' || obj_symbols.name
symbols_not_resolved = dbc.execute("""
SELECT packages.nvra, package_files.path, obj_symbols.name
FROM packages CROSS JOIN package_files CROSS JOIN obj_symbols FROM packages CROSS JOIN package_files CROSS JOIN obj_symbols
WHERE packages.repodir_id = ? AND packages.id = package_files.package_id AND WHERE packages.repodir_id = ? AND packages.id = package_files.package_id AND
package_files.id = obj_symbols.obj_file_id AND sym_type = 0 AND package_files.id = obj_symbols.obj_file_id AND sym_type = 0 AND
NOT EXISTS (SELECT 1 FROM obj_symbols_res WHERE obj_sym_id = obj_symbols.id) NOT EXISTS (SELECT 1 FROM obj_symbols_res WHERE obj_sym_id = obj_symbols.id)
""", [rd_id]).fetchall() """
if symbols_not_resolved: def print_reponame(self, repodir_id, repodir_name):
repodir_depends = get_repodir_depends(dbc, rd_id) print_reponame_with_depends(self.dbc, repodir_id, repodir_name)
if header:
print header class file_conflicts(query_output):
header = None title = 'File conflicts'
print ('%d) %s' % (rd_id, rd_name)) + \ def get_data(self, repodir_id):
('' if repodir_depends == '' else rows = self.dbc.execute("""
(' (depends on: %s)' % repodir_depends)) SELECT spf.path, sp.nvra, tp.nvra, tp.repodir_id
for sym_nr in symbols_not_resolved: FROM packages sp, package_files spf, package_files tpf, packages tp
print '\t%s: %s -?-> %s' % (sym_nr[0], sym_nr[1], sym_nr[2]) WHERE sp.id = spf.package_id AND sp.repodir_id = ? AND
print 'Total: %d' % len(symbols_not_resolved) spf.mode <> -1 AND (spf.mode & 16384) == 0 AND
spf.path = tpf.path AND spf.package_id <> tpf.package_id AND tpf.mode <> -1 AND
tpf.package_id = tp.id AND
tp.name <> sp.name AND
(tp.repodir_id == sp.repodir_id OR
tp.repodir_id IN
(SELECT rd.id FROM repodirs rd, repodir_depends rdd
WHERE depend_repodir_name = rd.name AND rdd.repodir_id = sp.repodir_id)) AND
NOT EXISTS (
SELECT 1 FROM package_conflicts_res pcr
WHERE (sp.id = pcr.package_id AND tp.id = pcr.dep_package_id) OR (tp.id = pcr.package_id AND sp.id = pcr.dep_package_id)
) AND
NOT EXISTS (
SELECT 1 FROM package_obsoletes_res por
WHERE (sp.id = por.package_id AND tp.id = por.dep_package_id) OR (tp.id = por.package_id AND sp.id = por.dep_package_id)
)
ORDER BY spf.path, sp.nvra, tp.nvra
""", [repodir_id]).fetchall()
# tp.name <> sp.name condition added to exclude different versions of the same package
pre_path = None
path_packages = []
result = []
for row in rows:
(path, pkg1, pkg2) = (row[0], row[1], row[2])
if row[3] != repodir_id:
pkg2 += ' {%s}' % self.get_repodir_name(row[3])
if path != pre_path and pre_path is not None:
result.append('%s: %s' % (pre_path, '; '.join(path_packages)))
path_packages = []
if pkg1 not in path_packages:
path_packages.append(pkg1)
if pkg2 not in path_packages:
path_packages.append(pkg2)
pre_path = path
if pre_path is not None:
result.append('%s: %s' % (pre_path, '; '.join(path_packages)))
return (result, len(result))
class provides_conflicts(query_output):
title = 'Provided capabilities conflicts'
def get_data(self, repodir_id):
rows = self.dbc.execute("""
SELECT srp.name, sp.nvra, tp.nvra, tp.repodir_id FROM packages sp, rpm_provides srp, rpm_provides trp, packages tp
WHERE sp.id = srp.package_id AND sp.repodir_id = ? AND
srp.name = trp.name AND srp.package_id <> trp.package_id AND
trp.package_id = tp.id AND
tp.name <> sp.name AND
(tp.repodir_id == sp.repodir_id OR
tp.repodir_id IN
(SELECT rd.id FROM repodirs rd, repodir_depends rdd
WHERE depend_repodir_name = rd.name AND rdd.repodir_id = sp.repodir_id)) AND
NOT EXISTS (
SELECT 1 FROM package_conflicts_res pcr
WHERE (sp.id = pcr.package_id AND tp.id = pcr.dep_package_id) OR (tp.id = pcr.package_id AND sp.id = pcr.dep_package_id)
) AND
NOT EXISTS (
SELECT 1 FROM package_obsoletes_res por
WHERE (sp.id = por.package_id AND tp.id = por.dep_package_id) OR (tp.id = por.package_id AND sp.id = por.dep_package_id)
) AND
EXISTS (SELECT 1 FROM rpm_requires WHERE rpm_requires.name = srp.name)
ORDER BY srp.name, sp.nvra, tp.nvra
""", [repodir_id]).fetchall()
# tp.name <> sp.name condition added to exclude different versions of the same package
pre_path = None
path_packages = []
result = []
for row in rows:
(path, pkg1, pkg2) = (row[0], row[1], row[2])
if row[3] != repodir_id:
pkg2 += ' {%s}' % self.get_repodir_name(row[3])
if path != pre_path and pre_path is not None:
result.append('%s: %s' % (pre_path, '; '.join(path_packages)))
path_packages = []
if pkg1 not in path_packages:
path_packages.append(pkg1)
if pkg2 not in path_packages:
path_packages.append(pkg2)
pre_path = path
if pre_path is not None:
result.append('%s: %s' % (pre_path, '; '.join(path_packages)))
return (result, len(result))
def main(args): def main(args):
options = parseargs() options = parseargs()
@ -524,12 +598,18 @@ def main(args):
dbc = conn.cursor() dbc = conn.cursor()
detect_broken_dependencies(dbc, options.dot_graphs) detect_broken_dependencies(dbc, options.dot_graphs)
#detect_loops(dbc) #detect_loops(dbc)
detect_lost_sources(dbc)
analyze_partitioning(dbc) analyze_partitioning(dbc)
detect_lost_object_files(dbc) lost_sources(dbc).print_text()
detect_broken_object_links(dbc) lost_object_files(dbc).print_text()
detect_so_needed_not_resolved(dbc) broken_object_links(dbc).print_text()
detect_symbols_not_resolved(dbc) so_needed_resolved1(dbc).print_text()
so_needed_resolved2(dbc).print_text()
so_needed_not_resolved(dbc).print_text()
symbols_resolved1_2(dbc).print_text()
symbols_resolved3(dbc).print_text()
symbols_not_resolved(dbc).print_text()
file_conflicts(dbc).print_text()
provides_conflicts(dbc).print_text()
conn.close() conn.close()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -21,7 +21,7 @@ gettext.install('urpm-tools')
DB = 'repo.db' DB = 'repo.db'
NUM_PROCESSES = 4 # number of CPU's (evaluated automatically) NUM_PROCESSES = 1 # number of CPU's (evaluated automatically)
RPMFILEMODE_DIRECTORY = 0x4000 RPMFILEMODE_DIRECTORY = 0x4000
RPMFILEMODE_EXECUTE = 0111 RPMFILEMODE_EXECUTE = 0111
@ -64,35 +64,35 @@ def to_string(rpm, tag, val):
return str(val).decode('utf-8', 'replace') return str(val).decode('utf-8', 'replace')
def init_database(conn): def init_database(conn):
conn.execute(""" conn.executescript("""
CREATE TABLE repodirs(id INTEGER PRIMARY KEY NOT NULL, CREATE TABLE repodirs(id INTEGER PRIMARY KEY NOT NULL,
name TEXT UNIQUE, path TEXT, arch TEXT, sources TEXT)""") name TEXT UNIQUE, path TEXT, arch TEXT, sources TEXT);
conn.execute("""
CREATE TABLE repodir_depends(id INTEGER PRIMARY KEY NOT NULL, CREATE TABLE repodir_depends(id INTEGER PRIMARY KEY NOT NULL,
repodir_id INTEGER, depend_repodir_name TEXT)""") repodir_id INTEGER, depend_repodir_name TEXT);
conn.execute("""
CREATE TABLE IF NOT EXISTS package_files(id INTEGER PRIMARY KEY NOT NULL, CREATE TABLE IF NOT EXISTS package_files(id INTEGER PRIMARY KEY NOT NULL,
package_id INTEGER NOT NULL, basename TEXT, path TEXT, package_id INTEGER NOT NULL, basename TEXT, path TEXT,
size INTEGER, mode INTEGER, size INTEGER, mode INTEGER,
link_to_file_id INTEGER, link_to_path TEXT, mark TEXT)""") link_to_file_id INTEGER, link_to_path TEXT, mark TEXT);
conn.execute(""" CREATE TABLE package_requires_res(id INTEGER PRIMARY KEY NOT NULL,
CREATE TABLE package_depend_res(id INTEGER PRIMARY KEY NOT NULL,
package_id INTEGER, requires_id INTEGER, package_id INTEGER, requires_id INTEGER,
provides_id INTEGER, dep_package_id INTEGER)""") provides_id INTEGER, dep_package_id INTEGER);
conn.execute(""" CREATE TABLE package_conflicts_res(id INTEGER PRIMARY KEY NOT NULL,
package_id INTEGER, conflicts_id INTEGER,
provides_id INTEGER, dep_package_id INTEGER);
CREATE TABLE package_obsoletes_res(id INTEGER PRIMARY KEY NOT NULL,
package_id INTEGER, obsoletes_id INTEGER,
provides_id INTEGER, dep_package_id INTEGER);
CREATE TABLE so_needed(id INTEGER PRIMARY KEY NOT NULL, CREATE TABLE so_needed(id INTEGER PRIMARY KEY NOT NULL,
obj_file_id INTEGER, name TEXT)""") obj_file_id INTEGER, name TEXT);
conn.execute("""
CREATE TABLE so_needed_res(id INTEGER PRIMARY KEY NOT NULL, CREATE TABLE so_needed_res(id INTEGER PRIMARY KEY NOT NULL,
so_needed_id INTEGER, dep_obj_file_id INTEGER, res_type INTEGER)""") so_needed_id INTEGER, dep_obj_file_id INTEGER, res_type INTEGER);
conn.execute("""
CREATE TABLE obj_symbols(id INTEGER PRIMARY KEY NOT NULL, CREATE TABLE obj_symbols(id INTEGER PRIMARY KEY NOT NULL,
obj_file_id INTEGER, name TEXT, sym_type INTEGER)""") obj_file_id INTEGER, name TEXT, sym_type INTEGER);
conn.execute("""
CREATE TABLE obj_symbols_res(id INTEGER PRIMARY KEY NOT NULL, CREATE TABLE obj_symbols_res(id INTEGER PRIMARY KEY NOT NULL,
obj_sym_id INTEGER, dep_obj_sym_id INTEGER, res_type INTEGER)""") obj_sym_id INTEGER, dep_obj_sym_id INTEGER, res_type INTEGER);
conn.execute("""PRAGMA synchronous = OFF""") PRAGMA synchronous = OFF;
conn.execute("""PRAGMA journal_mode = OFF""") PRAGMA journal_mode = OFF;
""")
def index_database(conn): def index_database(conn):
print 'Indexing the database...' print 'Indexing the database...'
@ -103,8 +103,12 @@ CREATE INDEX pkg_nvra ON packages(nvra);
CREATE INDEX pkg_arch ON packages(arch); CREATE INDEX pkg_arch ON packages(arch);
CREATE INDEX pkg_group ON packages(rpm_group); CREATE INDEX pkg_group ON packages(rpm_group);
CREATE INDEX pkg_repodir ON packages(repodir_id); CREATE INDEX pkg_repodir ON packages(repodir_id);
CREATE INDEX pkg_dr_pkg_req ON package_depend_res(package_id, requires_id); CREATE INDEX pkg_rq_pkg_req ON package_requires_res(package_id, requires_id);
CREATE INDEX pkg_dr_pkg_prov ON package_depend_res(dep_package_id, provides_id); CREATE INDEX pkg_rq_pkg_prov ON package_requires_res(dep_package_id, provides_id);
CREATE INDEX pkg_cf_pkg_conf ON package_conflicts_res(package_id, conflicts_id);
CREATE INDEX pkg_cf_pkg_prov ON package_conflicts_res(dep_package_id, provides_id);
CREATE INDEX pkg_ob_pkg_obs ON package_obsoletes_res(package_id, obsoletes_id);
CREATE INDEX pkg_ob_pkg_prov ON package_obsoletes_res(dep_package_id, provides_id);
CREATE INDEX pkg_file_pkg_id ON package_files(package_id); CREATE INDEX pkg_file_pkg_id ON package_files(package_id);
CREATE INDEX pkg_file_name ON package_files(basename); CREATE INDEX pkg_file_name ON package_files(basename);
CREATE INDEX pkg_file_path ON package_files(path); CREATE INDEX pkg_file_path ON package_files(path);
@ -356,7 +360,7 @@ def process_package_worker(num, queue_in, generator, gen_lock, db_struct,
files_dirs[file_path] = False files_dirs[file_path] = False
continue continue
dir_name = os.path.dirname(file_path) dir_name = os.path.dirname(file_path)
if dir_name not in files_dirs: if dir_name != '' and dir_name not in files_dirs:
files_dirs[dir_name] = True files_dirs[dir_name] = True
if no_shared_objects: if no_shared_objects:
continue continue
@ -687,6 +691,7 @@ CREATE TABLE IF NOT EXISTS %s (id INTEGER PRIMARY KEY NOT NULL,
def main(args): def main(args):
global NUM_PROCESSES
if os.path.exists(DB): if os.path.exists(DB):
os.unlink(DB) os.unlink(DB)

View file

@ -7,10 +7,210 @@ import gettext
import argparse import argparse
import sqlite3 import sqlite3
import re import re
from versutils import * import rpm
RPMSENSE_LESS = 0x02
RPMSENSE_GREATER = 0x04
RPMSENSE_EQUAL = 0x08
RPMSENSE_SENSEMASK = 0x0f
RPMSENSE_FIND_PROVIDES = 0x8000
RPMSENSE_MISSINGOK = 0x80000
RPMSENSE_SCRIPT_POST = 0x400
RPMSENSE_SCRIPT_PREUN = 0x800
RPMSENSE_SCRIPT_POSTUN = 0x1000
DB = 'repo.db' DB = 'repo.db'
def version_ok(required_version, compare_flag, candidate_version):
def sep_version(version):
vrem = re.match(r'\A(.+)(\-[^\-\:]+)(\:[^\:]+|)\Z', version)
if vrem:
return (vrem.group(1), vrem.group(2), vrem.group(3))
return (version, '', '')
def simple_version(version):
version = re.sub(r'[\-:]', '.', version)
version = re.sub(r'[a-z]+', '.', version, flags=re.I)
version = re.sub(r'\.\Z', '', version)
return version
def format_versions(ver1, ver2):
#see urpm-repoclosure, formatVersions
# v1 - provided
# v2 - required
(e1, e2) = (None, None)
e1_m = re.match(r'\A([^\-\:]+)\:(.*)', ver1)
if e1_m:
(e1, ver1) = (e1_m.group(1), e1_m.group(2))
e2_m = re.match(r'\A([^\-\:]+)\:(.*)', ver2)
if e2_m:
(e2, ver2) = (e2_m.group(1), e2_m.group(2))
(ver1_m, ver1_r, ver1_rr) = sep_version(ver1)
(ver2_m, ver2_r, ver2_rr) = sep_version(ver2)
if not ver2_rr:
ver1_rr = ''
if not ver2_r:
ver1_r = ''
ver1 = ver1_m + ver1_r + ver1_rr
ver2 = ver2_m + ver2_r + ver2_rr
if e1_m and e2_m:
ver1 = e1 + '.' + ver1
ver2 = e2 + '.' + ver2
return (simple_version(ver1), simple_version(ver2))
def cmp_nums(num1, num2):
# 00503
# 12
if num1 == num2:
return 0
lzeros1 = re.match(r'\A([0]+)([1-9].*)', num1)
if lzeros1:
(num1, num2) = (lzeros1.group(2), num2 + lzeros1.group(1))
lzeros2 = re.match(r'\A([0]+)([1-9].*)', num2)
if lzeros2:
(num2, num1) = (lzeros2.group(2), num1 + lzeros2.group(1))
diff = int(num1, 10) - int(num2, 10)
return 0 if diff == 0 else \
(1 if diff > 0 else -1)
def cmp_versions(version1, version2):
#see urpm-repoclosure, cmpVersions
# 3.2.5-5:2011.0
# NOTE: perl 5.00503 and 5.12
(v1, v2) = format_versions(version1, version2)
if v1 == v2:
return 0
v1parts = v1.split('.')
v2parts = v2.split('.')
for i in xrange(0, min(len(v1parts), len(v2parts))):
(num1, num2)= (v1parts[i], v2parts[i])
if (len(num1) > 0 and len(num2) == 0):
return 1
if (len(num1) == 0 and len(num2) > 0):
return -1
num_diff = cmp_nums(num1, num2)
if num_diff != 0:
return num_diff
if len(v1parts) < len(v2parts):
return -1
if len(v1parts) > len(v2parts):
return 1
return 0
def rpm_cmp_versions(version1, version2):
def stringToVersion(verstring):
# from rpmUtils
if verstring in [None, '']:
return (None, None, None)
e1_m = re.match(r'\A([^\-\:]+)\:(.*)', verstring)
epoch = None
if e1_m:
(epoch, verstring) = (e1_m.group(1), e1_m.group(2))
j = verstring.find('-')
if j != -1:
if verstring[:j] == '':
version = None
else:
version = verstring[:j]
release = verstring[j + 1:]
else:
if verstring == '':
version = None
else:
version = verstring
release = None
return (epoch, version, release)
(e1, v1, r1) = stringToVersion(version1)
(e2, v2, r2) = stringToVersion(version2)
if e1 is None or e2 is None:
e1 = '0'
e2 = '0'
result = rpm.labelCompare((e1, v1, r1), (e2, v2, r2))
return result
# print '===', required_version, compare_flag, candidate_version
if compare_flag == 0:
return True
if candidate_version == '*':
return True
#see urpm-repoclosure, checkDeps
if compare_flag == RPMSENSE_EQUAL and \
candidate_version == required_version:
return True
cmp_res = None
try:
cmp_res = cmp_versions(candidate_version, required_version)
except ValueError as ex:
print ('Error when comparing versions: "%s" and "%s"\n%s' %
(candidate_version, required_version, str(ex)))
return False
rpm_cmp_res = rpm_cmp_versions(candidate_version, required_version)
#if (cmp_res != rpm_cmp_res):
#print >> sys.stderr, ('Invalid compare: "%s" vs "%s"! Results: rc: %d, rpm: %d.' %
#(candidate_version, required_version, cmp_res, rpm_cmp_res))
if compare_flag == RPMSENSE_EQUAL:
return cmp_res == 0
elif compare_flag == RPMSENSE_LESS | RPMSENSE_EQUAL:
return cmp_res <= 0
elif compare_flag == RPMSENSE_GREATER | RPMSENSE_EQUAL:
return cmp_res >= 0
elif compare_flag == RPMSENSE_LESS:
return cmp_res < 0
elif compare_flag == RPMSENSE_GREATER:
return cmp_res > 0
return False
def process_repodir_dependencies(dbc, repodir_id, repodir_name, repodir_depends, dep_type):
package_depends = dbc.execute("""
SELECT packages.id AS package_id, packages.name AS package_name, packages.nvra,
dep.id, dep.name, flags, dep.version
FROM packages, rpm_%s dep
WHERE repodir_id = ? AND dep.package_id = packages.id
ORDER BY packages.name, dep.name
""" % dep_type, [repodir_id]).fetchall()
search_repodirs = [repodir_id]
search_repodirs.extend(repodir_depends)
in_repodirs = ','.join(str(id) for id in search_repodirs)
dependency_cache = {}
for packdep in package_depends:
(cpackage_id, package_nvra, dep_id, dep_name, dep_flags, dep_version) = \
(packdep[0], packdep[2], packdep[3], packdep[4], packdep[5], packdep[6])
dependency_uid = dep_name + '\x00' + str(dep_flags) + '\x00' + dep_version
dep_res = dependency_cache.get(dependency_uid, None)
if dep_res is None:
dep_res = []
depend_candidates = dbc.execute("""
SELECT packages.id AS package_id, packages.name AS package_name, packages.nvra,
prov.id, prov.name, flags, prov.version
FROM packages, rpm_provides AS prov
WHERE prov.package_id = packages.id AND repodir_id IN (%s) AND prov.name = ?
ORDER by packages.name, packages.nvra
""" % in_repodirs, [dep_name]).fetchall()
for dep_cand in depend_candidates:
(pkg_id, provides_id, provides_flags, provides_version) = \
(dep_cand[0], dep_cand[3], dep_cand[5], dep_cand[6])
if provides_flags & RPMSENSE_SENSEMASK == 0:
if not provides_version:
provides_version = '*'
else:
raise Exception('Invalid provides version '
'(flags = %d, version = %s)!' %
(provides_flags, provides_version))
if version_ok(dep_version, dep_flags & RPMSENSE_SENSEMASK,
provides_version):
dep_res.append({'prov_id': provides_id, 'pkg_id': pkg_id})
if len(dep_res) > 0:
for res_rec in dep_res:
dbc.execute("""
INSERT INTO package_%(dep)s_res(package_id, %(dep)s_id,
provides_id, dep_package_id)
VALUES (?, ?, ?, ?)""" % {'dep': dep_type}, [cpackage_id, dep_id,
res_rec.get('prov_id'), res_rec.get('pkg_id')])
dependency_cache[dependency_uid] = dep_res
def process_repodir_requires(dbc, repodir_id, repodir_name, repodir_depends, requires_build_arch): def process_repodir_requires(dbc, repodir_id, repodir_name, repodir_depends, requires_build_arch):
global n global n
@ -37,13 +237,13 @@ SELECT packages.id AS package_id, packages.name AS package_name, packages.nvra,
(cpackage_id, package_nvra, requires_id, requires_name, requires_flags, requires_version) = \ (cpackage_id, package_nvra, requires_id, requires_name, requires_flags, requires_version) = \
(packreq[0], packreq[2], packreq[3], packreq[4], packreq[5], packreq[6]) (packreq[0], packreq[2], packreq[3], packreq[4], packreq[5], packreq[6])
requirement_uid = requires_name + '\0' + str(requires_flags) + '\0' + requires_version requirement_uid = requires_name + '\x00' + str(requires_flags) + '\x00' + requires_version
dep_res = requires_cache.get(requirement_uid, None) req_res = requires_cache.get(requirement_uid, None)
if dep_res is None: if req_res is None:
dep_res = [] req_res = []
if (re.match(r'\A(rpmlib|executable)\(.+\)\Z', requires_name)): if (re.match(r'\A(rpmlib|executable)\(.+\)\Z', requires_name)):
# see if($N=~/\A(rpmlib|executable)\(.+\)\Z/) in urpm_repoclosure.pl # see if($N=~/\A(rpmlib|executable)\(.+\)\Z/) in urpm_repoclosure.pl
dep_res.append({}) req_res.append({})
else: else:
depend_candidates = dbc.execute(""" depend_candidates = dbc.execute("""
SELECT packages.id AS package_id, packages.name AS package_name, packages.nvra, SELECT packages.id AS package_id, packages.name AS package_name, packages.nvra,
@ -83,11 +283,11 @@ SELECT packages.id AS package_id, packages.name AS package_name, packages.nvra,
if provides_version == preferred_version or \ if provides_version == preferred_version or \
version_ok(provides_version, RPMSENSE_EQUAL, version_ok(provides_version, RPMSENSE_EQUAL,
preferred_version): preferred_version):
dep_res.append({'prov_id': provides_id, req_res.append({'prov_id': provides_id,
'pkg_id': pkg_id}) 'pkg_id': pkg_id})
if len(dep_res) == 0 and requires_name.startswith('/'): # file dependency if len(req_res) == 0 and requires_name.startswith('/'): # file dependency
if (requires_flags & (RPMSENSE_SCRIPT_POST | if (requires_flags & (RPMSENSE_SCRIPT_POST |
RPMSENSE_SCRIPT_PREUN | RPMSENSE_SCRIPT_PREUN |
RPMSENSE_SCRIPT_POSTUN)) != 0: RPMSENSE_SCRIPT_POSTUN)) != 0:
@ -95,7 +295,7 @@ SELECT packages.id AS package_id, packages.name AS package_name, packages.nvra,
SELECT COUNT(1) FROM package_files WHERE package_id = ? AND path = ? SELECT COUNT(1) FROM package_files WHERE package_id = ? AND path = ?
""", [cpackage_id, requires_name]).fetchone() """, [cpackage_id, requires_name]).fetchone()
if int_files_cnt[0] > 0: if int_files_cnt[0] > 0:
dep_res.append({}) req_res.append({})
else: else:
#TODO: Check file dependencies (/usr/bin/python (required by ant-scripts-1.7.1-7.0.6.noarch), /usr/sbin/useradd (required by tomcat5-5.5.28-0.5.2.noarch))? #TODO: Check file dependencies (/usr/bin/python (required by ant-scripts-1.7.1-7.0.6.noarch), /usr/sbin/useradd (required by tomcat5-5.5.28-0.5.2.noarch))?
files_deps = dbc.execute(""" files_deps = dbc.execute("""
@ -104,22 +304,22 @@ SELECT package_id FROM package_files
package_id in (SELECT id FROM packages WHERE repodir_id IN (%s)) package_id in (SELECT id FROM packages WHERE repodir_id IN (%s))
""" % in_repodirs, [requires_name]).fetchall() """ % in_repodirs, [requires_name]).fetchall()
for file_dep in files_deps: for file_dep in files_deps:
dep_res.append({'pkg_id': file_dep[0]}) req_res.append({'pkg_id': file_dep[0]})
if len(dep_res) == 0 and (requires_flags & RPMSENSE_MISSINGOK) != 0: if len(req_res) == 0 and (requires_flags & RPMSENSE_MISSINGOK) != 0:
dep_res.append({}) req_res.append({})
if len(dep_res) > 0: if len(req_res) > 0:
for res_rec in dep_res: for res_rec in req_res:
dbc.execute(""" dbc.execute("""
INSERT INTO package_depend_res(package_id, requires_id, INSERT INTO package_requires_res(package_id, requires_id,
provides_id, dep_package_id) provides_id, dep_package_id)
VALUES (?, ?, ?, ?) VALUES (?, ?, ?, ?)
""", [cpackage_id, requires_id, res_rec.get('prov_id'), res_rec.get('pkg_id')]) """, [cpackage_id, requires_id, res_rec.get('prov_id'), res_rec.get('pkg_id')])
else: else:
print requires_name, ' ', requires_version, ' (required by %s)' % package_nvra, ' not found!!!' print requires_name, ' ', requires_version, ' (required by %s)' % package_nvra, ' not found!!!'
broken_dep += 1 broken_dep += 1
requires_cache[requirement_uid] = dep_res requires_cache[requirement_uid] = req_res
n = n + 1 n = n + 1
#print "n = ", n #print "n = ", n
# if n == 60000: # if n == 60000:
@ -150,7 +350,6 @@ SELECT packages.id AS package_id, packages.name AS package_name, packages.nvra,
""", [repodir_id]).fetchall() """, [repodir_id]).fetchall()
for file_link in package_files_links: for file_link in package_files_links:
pkg_id = file_link[0] pkg_id = file_link[0]
pkg_name = file_link[1]
pkg_nvra = file_link[2] pkg_nvra = file_link[2]
object_id = file_link[3] object_id = file_link[3]
target_obj_id = None target_obj_id = None
@ -169,10 +368,10 @@ SELECT id, link_to_path FROM package_files WHERE path = ? AND package_id = ?
# Just two levels of dependency recursion - TODO: Full depth recursion? # Just two levels of dependency recursion - TODO: Full depth recursion?
tofile = dbc.execute(""" tofile = dbc.execute("""
SELECT id, link_to_path FROM package_files WHERE path = ? AND package_id IN ( SELECT id, link_to_path FROM package_files WHERE path = ? AND package_id IN (
SELECT dep_package_id FROM package_depend_res WHERE package_id = ? SELECT dep_package_id FROM package_requires_res WHERE package_id = ?
UNION UNION
SELECT dep_package_id FROM package_depend_res WHERE package_id IN SELECT dep_package_id FROM package_requires_res WHERE package_id IN
(SELECT dep_package_id FROM package_depend_res WHERE package_id = ?) (SELECT dep_package_id FROM package_requires_res WHERE package_id = ?)
) )
""", [target_path, pkg_id, pkg_id]).fetchone() """, [target_path, pkg_id, pkg_id]).fetchone()
if tofile: if tofile:
@ -201,14 +400,14 @@ def process_repodir_so_needed(dbc, repodir_id, repodir_name, repodir_depends):
INSERT INTO so_needed_res(so_needed_id, dep_obj_file_id, res_type) INSERT INTO so_needed_res(so_needed_id, dep_obj_file_id, res_type)
SELECT so_needed.id, tpf.id, 1 FROM packages SELECT so_needed.id, tpf.id, 1 FROM packages
CROSS JOIN package_files spf CROSS JOIN so_needed CROSS JOIN rpm_requires CROSS JOIN package_files spf CROSS JOIN so_needed CROSS JOIN rpm_requires
CROSS JOIN package_depend_res dep_res CROSS JOIN package_files tpf CROSS JOIN package_requires_res req_res CROSS JOIN package_files tpf
WHERE so_needed.obj_file_id = spf.id AND spf.package_id = packages.id AND WHERE so_needed.obj_file_id = spf.id AND spf.package_id = packages.id AND
packages.repodir_id = ? AND spf.package_id = rpm_requires.package_id AND packages.repodir_id = ? AND spf.package_id = rpm_requires.package_id AND
(so_needed.name = rpm_requires.name OR (so_needed.name = rpm_requires.name OR
so_needed.name || '()(64bit)' = rpm_requires.name) AND so_needed.name || '()(64bit)' = rpm_requires.name) AND
packages.id = dep_res.package_id AND packages.id = req_res.package_id AND
rpm_requires.id = dep_res.requires_id AND rpm_requires.id = req_res.requires_id AND
dep_res.dep_package_id = tpf.package_id AND req_res.dep_package_id = tpf.package_id AND
so_needed.name = tpf.basename so_needed.name = tpf.basename
""", [repodir_id]) """, [repodir_id])
@ -307,6 +506,8 @@ SELECT id, name FROM repodirs WHERE id IN (%s) AND name = ?
if not all_depends_ready: if not all_depends_ready:
return False return False
print repo_name, ' ', depend_repodir_list, ' ', dep_arch print repo_name, ' ', depend_repodir_list, ' ', dep_arch
process_repodir_dependencies(dbc, repo_id, repo_name, repodir_depends, 'conflicts')
process_repodir_dependencies(dbc, repo_id, repo_name, repodir_depends, 'obsoletes')
process_repodir_requires(dbc, repo_id, repo_name, repodir_depends, dep_arch) process_repodir_requires(dbc, repo_id, repo_name, repodir_depends, dep_arch)
process_repodir_file_links(dbc, repo_id, repo_name, repodir_depends) process_repodir_file_links(dbc, repo_id, repo_name, repodir_depends)
process_repodir_so_needed(dbc, repo_id, repo_name, repodir_depends) process_repodir_so_needed(dbc, repo_id, repo_name, repodir_depends)
@ -315,9 +516,6 @@ SELECT id, name FROM repodirs WHERE id IN (%s) AND name = ?
if repo_sources: if repo_sources:
print 'Searching source rpms...' print 'Searching source rpms...'
dbc.execute(""" dbc.execute("""
UPDATE packages SET sourcerpm_package = NULL
WHERE repodir_id = ?""", [repo_id])
dbc.execute("""
UPDATE packages SET sourcerpm_package = UPDATE packages SET sourcerpm_package =
(SELECT id FROM packages ps (SELECT id FROM packages ps
WHERE repodir_id IN (SELECT id FROM repodirs WHERE name = ?) AND WHERE repodir_id IN (SELECT id FROM repodirs WHERE name = ?) AND
@ -334,17 +532,17 @@ def main(args):
global n global n
n = 0 n = 0
dbc.execute(""" dbc.executescript("""
PRAGMA cache_size = -1048576 PRAGMA cache_size = -1048576;
""") DELETE FROM package_requires_res;
dbc.execute(""" DELETE FROM package_conflicts_res;
DELETE FROM so_needed_res""") DELETE FROM package_obsoletes_res;
dbc.execute(""" DELETE FROM so_needed_res;
DELETE FROM obj_symbols_res""") DELETE FROM obj_symbols_res;
dbc.execute(""" UPDATE package_files SET link_to_file_id = NULL;
DELETE FROM package_depend_res""") UPDATE packages SET sourcerpm_package = NULL;
dbc.execute(""" ANALYZE;
ANALYZE""") """)
repodirs_processed = [] repodirs_processed = []
#Process binary rpms #Process binary rpms
repodirs_processed_cnt = -1 repodirs_processed_cnt = -1

View file

@ -1,151 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import re
import rpm
RPMSENSE_LESS = 0x02
RPMSENSE_GREATER = 0x04
RPMSENSE_EQUAL = 0x08
RPMSENSE_SENSEMASK = 0x0f
RPMSENSE_FIND_PROVIDES = 0x8000
RPMSENSE_MISSINGOK = 0x80000
RPMSENSE_SCRIPT_POST = 0x400
RPMSENSE_SCRIPT_PREUN = 0x800
RPMSENSE_SCRIPT_POSTUN = 0x1000
def version_ok(required_version, compare_flag, candidate_version):
def sep_version(version):
vrem = re.match(r'\A(.+)(\-[^\-\:]+)(\:[^\:]+|)\Z', version)
if vrem:
return (vrem.group(1), vrem.group(2), vrem.group(3))
return (version, '', '')
def simple_version(version):
version = re.sub(r'[\-:]', '.', version)
version = re.sub(r'[a-z]+', '.', version, flags=re.I)
version = re.sub(r'\.\Z', '', version)
return version
def format_versions(ver1, ver2):
#see urpm-repoclosure, formatVersions
# v1 - provided
# v2 - required
(e1, e2) = (None, None)
e1_m = re.match(r'\A([^\-\:]+)\:(.*)', ver1)
if e1_m:
(e1, ver1) = (e1_m.group(1), e1_m.group(2))
e2_m = re.match(r'\A([^\-\:]+)\:(.*)', ver2)
if e2_m:
(e2, ver2) = (e2_m.group(1), e2_m.group(2))
(ver1_m, ver1_r, ver1_rr) = sep_version(ver1)
(ver2_m, ver2_r, ver2_rr) = sep_version(ver2)
if not ver2_rr:
ver1_rr = ''
if not ver2_r:
ver1_r = ''
ver1 = ver1_m + ver1_r + ver1_rr
ver2 = ver2_m + ver2_r + ver2_rr
if e1_m and e2_m:
ver1 = e1 + '.' + ver1
ver2 = e2 + '.' + ver2
return (simple_version(ver1), simple_version(ver2))
def cmp_nums(num1, num2):
# 00503
# 12
if num1 == num2:
return 0
lzeros1 = re.match(r'\A([0]+)([1-9].*)', num1)
if lzeros1:
(num1, num2) = (lzeros1.group(2), num2 + lzeros1.group(1))
lzeros2 = re.match(r'\A([0]+)([1-9].*)', num2)
if lzeros2:
(num2, num1) = (lzeros2.group(2), num1 + lzeros2.group(1))
diff = int(num1) - int(num2)
return 0 if diff == 0 else \
(1 if diff > 0 else -1)
def cmp_versions(version1, version2):
#see urpm-repoclosure, cmpVersions
# 3.2.5-5:2011.0
# NOTE: perl 5.00503 and 5.12
(v1, v2) = format_versions(version1, version2)
if v1 == v2:
return 0
v1parts = v1.split('.')
v2parts = v2.split('.')
for i in xrange(0, min(len(v1parts), len(v2parts))):
(num1, num2)= (v1parts[i], v2parts[i])
if (len(num1) > 0 and len(num2) == 0):
return 1
if (len(num1) == 0 and len(num2) > 0):
return -1
num_diff = cmp_nums(num1, num2)
if num_diff != 0:
return num_diff
if len(v1parts) < len(v2parts):
return -1
if len(v1parts) > len(v2parts):
return 1
return 0
def rpm_cmp_versions(version1, version2):
def stringToVersion(verstring):
# from rpmUtils
if verstring in [None, '']:
return (None, None, None)
e1_m = re.match(r'\A([^\-\:]+)\:(.*)', verstring)
epoch = None
if e1_m:
(epoch, verstring) = (e1_m.group(1), e1_m.group(2))
j = verstring.find('-')
if j != -1:
if verstring[:j] == '':
version = None
else:
version = verstring[:j]
release = verstring[j + 1:]
else:
if verstring == '':
version = None
else:
version = verstring
release = None
return (epoch, version, release)
(e1, v1, r1) = stringToVersion(version1)
(e2, v2, r2) = stringToVersion(version2)
if e1 is None or e2 is None:
e1 = '0'
e2 = '0'
result = rpm.labelCompare((e1, v1, r1), (e2, v2, r2))
return result
# print '===', required_version, compare_flag, candidate_version
if compare_flag == 0:
return True
if candidate_version == '*':
return True
#see urpm-repoclosure, checkDeps
if compare_flag == RPMSENSE_EQUAL and \
candidate_version ==required_version:
return True
cmp_res = cmp_versions(candidate_version, required_version)
rpm_cmp_res = rpm_cmp_versions(candidate_version, required_version)
#if (cmp_res != rpm_cmp_res):
#print >> sys.stderr, ('Invalid compare: "%s" vs "%s"! Results: rc: %d, rpm: %d.' %
#(candidate_version, required_version, cmp_res, rpm_cmp_res))
if compare_flag == RPMSENSE_EQUAL:
return cmp_res == 0
elif compare_flag == RPMSENSE_LESS | RPMSENSE_EQUAL:
return cmp_res <= 0
elif compare_flag == RPMSENSE_GREATER | RPMSENSE_EQUAL:
return cmp_res >= 0
elif compare_flag == RPMSENSE_LESS:
return cmp_res < 0
elif compare_flag == RPMSENSE_GREATER:
return cmp_res > 0
return False