introduce ability to find reverse dependencies recursively

The change is introducing two options: --recursive and
--recursive-depth. So user will be able to print the full chain of
reverse-deps.

Signed-off-by: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@canonical.com>
This commit is contained in:
Sahid Orentino Ferdjaoui 2019-07-04 19:06:20 +02:00
parent ae9c80de37
commit 5cf0f000db

View File

@ -24,6 +24,7 @@ from ubuntutools.misc import (system_distribution, vendor_to_distroinfo,
codename_to_distribution)
from ubuntutools.rdepends import query_rdepends, RDependsException
DEFAULT_MAX_DEPTH = 10 # We want avoid any infinite loop...
def main():
system_distro_info = vendor_to_distroinfo(system_distribution())()
@ -67,6 +68,12 @@ def main():
dest='server', default=None,
help='Reverse Dependencies webservice URL. '
'Default: UbuntuWire')
parser.add_option('-x', '--recursive',
action='store_true', dest='recursive', default=False,
help='Consider to find reverse dependencies recursively.')
parser.add_option('-d', '--recursive-deph', type="int",
metavar='RECURSIVE_DEPTH', dest='recursive_depth', default=DEFAULT_MAX_DEPTH,
help='If recusive, you can specify the depth.')
options, args = parser.parse_args()
@ -90,11 +97,26 @@ def main():
# We already printed a warning
pass
try:
data = query_rdepends(package, options.release, options.arch, **opts)
except RDependsException, e:
Logger.error(str(e))
sys.exit(1)
def query(package):
try:
return query_rdepends(package, options.release, options.arch, **opts)
except RDependsException, e:
Logger.error(str(e))
sys.exit(1)
def filter_out_fiels(data, fields):
for field in data.keys():
if field not in fields:
del data[field]
def filter_out_component(data, component):
for field, rdeps in data.items():
filtered = [rdep for rdep in rdeps
if rdep['Component'] in component]
if not filtered:
del data[field]
else:
data[field] = filtered
if options.arch == 'source':
fields = ['Reverse-Build-Depends', 'Reverse-Build-Depends-Indep']
@ -105,50 +127,81 @@ def main():
if options.suggests:
fields.append('Reverse-Suggests')
for field in data.keys():
if field not in fields:
del data[field]
def build_results(package, result, fields, component, recursive):
data = query(package)
if not data:
return
if options.component:
for field, rdeps in data.items():
filtered = [rdep for rdep in rdeps
if rdep['Component'] in options.component]
if not filtered:
del data[field]
else:
data[field] = filtered
result[package] = data
if fields:
filter_out_fiels(result[package], fields)
if component:
filter_out_component(result[package], component)
if recursive > 0:
for rdeps in result[package].itervalues():
for rdep in rdeps:
build_results(
rdep['Package'], result, fields, component, recursive - 1)
result = {}
build_results(
package, result, fields, options.component,
options.recursive and options.recursive_depth or 0)
if options.list:
display_consise(data)
display_consise(result)
else:
display_verbose(data)
display_verbose(package, result)
def display_verbose(data):
if not data:
def display_verbose(package, values):
if not values:
print "No reverse dependencies found"
return
all_archs = set()
# This isn't accurate, but we make up for it by displaying what we found
for rdeps in data.itervalues():
for rdep in rdeps:
if 'Architectures' in rdep:
all_archs.update(rdep['Architectures'])
for field, rdeps in data.iteritems():
def print_field(field):
print field
print '=' * len(field)
def print_package(values, package, arch, dependency, offset=0):
line = ' ' * offset + '* %s' % package
if all_archs and set(arch) != all_archs:
line += ' [%s]' % ' '.join(sorted(arch))
if dependency:
if len(line) < 30:
line += ' ' * (30 - len(line))
line += ' (for %s)' % dependency
print line
data = values.get(package)
if data:
offset = offset + 1
for rdeps in data.itervalues():
for rdep in rdeps:
print_package(values,
rdep['Package'],
rdep['Architectures'],
rdep.get('Dependency'),
offset)
all_archs = set()
# This isn't accurate, but we make up for it by displaying what we found
for data in values.itervalues():
for rdeps in data.itervalues():
for rdep in rdeps:
if 'Architectures' in rdep:
all_archs.update(rdep['Architectures'])
for field, rdeps in values[package].iteritems():
print_field(field)
rdeps.sort(key=lambda x: x['Package'])
for rdep in rdeps:
line = '* %s' % rdep['Package']
if all_archs and set(rdep['Architectures']) != all_archs:
line += ' [%s]' % ' '.join(sorted(rdep['Architectures']))
if 'Dependency' in rdep:
if len(line) < 30:
line += ' ' * (30 - len(line))
line += ' (for %s)' % rdep['Dependency']
print line
print_package(values,
rdep['Package'],
rdep['Architectures'],
rdep.get('Dependency'))
print
if all_archs:
@ -157,11 +210,12 @@ def display_verbose(data):
% ', '.join(sorted(list(all_archs))))
def display_consise(data):
def display_consise(values):
result = set()
for rdeps in data.itervalues():
for rdep in rdeps:
result.add(rdep['Package'])
for data in values.itervalues():
for rdeps in data.itervalues():
for rdep in rdeps:
result.add(rdep['Package'])
print u'\n'.join(sorted(list(result)))