Версия скрипта с "белым списком"
Для случая с firefox приведенного выше:
$./DepTree.py firefox-vimperator firefox+
#!/usr/bin/python3
import subprocess
import sys
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
def get_dependency(package):
if package == "":
return None
resp = subprocess.check_output(["rpm", "--requires", "--qf", "'%{REQUIRENAME}'", "-q", package],
universal_newlines=True)
s = str(resp)
# eprint(s)
if s and len(s.strip()) > 0:
return s.replace("'", "").split(sep="\n")
else:
return None
def get_all_packages():
resp = subprocess.check_output(["rpm", "-qa", "--qf", "'%{name}\n'"], universal_newlines=True)
s = str(resp)
return s.replace("'", "").split("\n")
def get_whats_req(package):
args = ["/bin/sh", "-c",
"rpm --test -e " + package +
" 2>&1 >/dev/null | egrep -o -e 'для.+' | sed 's/для //' | sed 's/-[^-]*-[^-]*$//'"]
resp = subprocess.check_output(args, universal_newlines=True, stderr=None)
s = str(resp).strip("\n")
if s and len(s.strip()) > 0:
return s.replace("'", "").split(sep="\n")
else:
return None
candidats = {}
all_packages = get_all_packages()
blacklist = set()
whitelist = set()
def process_pckg_list(pckg_list):
# eprint(blacklist)
for package in pckg_list:
try:
dep = candidats[package]
has_before = True
except KeyError:
dep = set()
candidats[package] = dep
has_before = False
try:
dep_list = get_dependency(package)
if dep_list is None:
return True
except subprocess.CalledProcessError:
eprint("error while processing :", package)
# xtree.pop(package)
return False
for s in dep_list:
s = s.strip()
if len(s) == 0:
continue
if "(" in s:
continue
if "/" in s:
continue
if s in whitelist:
continue
try:
pname = s.strip().split()[0].strip()
except IndexError:
eprint("index error:", s)
continue
if pname in blacklist:
continue
# print(package, "::", s,"->",pname)
dep.add(pname)
if pname not in candidats:
status = process_pckg_list([pname])
if not status:
try:
if not has_before:
eprint("blacklist:", pname)
blacklist.add(pname)
del candidats[pname]
except KeyError:
pass
return True
def main():
args = sys.argv
args.pop(0)
args1 = set(args.copy())
for p in args:
if p[-1] == '+':
whitelist.add(p[0:-1])
try:
args1.remove(p)
except KeyError:
pass
continue
deps = get_whats_req(p)
if deps:
args1 = args1.union(set(deps))
args1 -= whitelist
eprint(args1)
eprint(whitelist)
process_pckg_list(args1)
pass_count = 1
class NeedPassException(Exception):
pass
dep_cache = {}
while True:
pass_count += 1
need_next_pass = False
try:
for p in candidats:
try:
deps = dep_cache[p]
except KeyError:
try:
deps = get_whats_req(p)
dep_cache[p] = deps
except subprocess.CalledProcessError:
dep_cache[p] = []
continue
if deps is None:
continue
for r in deps:
r = r.strip()
if len(r) == 0:
continue
if r == p:
continue
if r not in all_packages:
continue
if r not in candidats or r in whitelist:
# noinspection PyUnusedLocal
need_next_pass = True
xlist = candidats[p]
for c1 in xlist:
try:
del candidats[c1]
except KeyError:
pass
try:
del candidats[p]
except KeyError:
pass
raise NeedPassException
pass
pass
except NeedPassException:
continue
if not need_next_pass:
break
pass
result = ''
eprint("Всего найдено пакетов для удаления:", len(candidats))
for s in candidats.keys():
result = result + s + " "
print(result)
if __name__ == "__main__":
main()