Чего-то получилось...
$ sudo apt-get remove `python3 ./DepTree.py xfce4-default`
{'xfce4-default', 'xfce4-full', 'xfce4-regular'}
предупреждение: пакет xfce-freedesktop-menu не установлен
erron while processing : xfce-freedesktop-menu
blacklist: xfce-freedesktop-menu
предупреждение: пакет pam-common не установлен
erron while processing : pam-common
blacklist: pam-common
предупреждение: пакет glibc-crypt_blowfish не установлен
erron while processing : glibc-crypt_blowfish
blacklist: glibc-crypt_blowfish
предупреждение: пакет cpp не установлен
erron while processing : cpp
blacklist: cpp
предупреждение: пакет ntfsprogs не установлен
erron while processing : ntfsprogs
blacklist: ntfsprogs
предупреждение: пакет screen-saver-engine не установлен
erron while processing : screen-saver-engine
blacklist: screen-saver-engine
Всего найдено пакетов для удаления: 102
Чтение списков пакетов... Завершено
Построение дерева зависимостей... Завершено
Следующие пакеты будут УДАЛЕНЫ:
dconf eject enchant gnome-online-accounts gst-plugins-bad1.0 gst-plugins-good1.0 gtk2-themes-xfce4 gvfs gvfs-backend-admin gvfs-backend-afc gvfs-backend-afp
gvfs-backend-cdda gvfs-backend-dnssd gvfs-backend-goa gvfs-backend-google gvfs-backend-mtp gvfs-backend-nfs gvfs-backend-recent-files gvfs-backend-smb
gvfs-backends hddtemp libdconf libgarcon-settings-manager-menu libthunar libtumbler libupower libxfce4panel libxfsm lm_sensors3 mousepad nfs-clients
nfs-utils orage parole pavucontrol realmd ristretto rodent-icon-theme rpcbind samba-client samba-common-libs samba-common-tools samba-libs thunar
thunar-archive-plugin thunar-media-tags-plugin thunar-volman-plugin tumbler unzip upower xarchiver xdg-user-dirs xfce-polkit xfce4-about xfce4-appfinder
xfce4-battery-plugin xfce4-calculator-plugin xfce4-clipman-plugin xfce4-cpufreq-plugin xfce4-cpugraph-plugin xfce4-datetime-plugin xfce4-default xfce4-dict
xfce4-diskperf-plugin xfce4-eyes-plugin xfce4-fsguard-plugin xfce4-full xfce4-genmon-plugin xfce4-hardware-monitor-plugin xfce4-kbdleds-plugin
xfce4-mailwatch-plugin xfce4-minimal xfce4-mount-plugin xfce4-netload-plugin xfce4-notes-plugin xfce4-notifyd xfce4-panel xfce4-places-plugin
xfce4-power-manager xfce4-pulseaudio-plugin xfce4-quicklauncher-plugin xfce4-regular xfce4-screenshooter xfce4-sensors-plugin xfce4-session
xfce4-session-engines xfce4-settings xfce4-smartbookmark-plugin xfce4-systemload-plugin xfce4-taskmanager xfce4-terminal xfce4-time-out-plugin
xfce4-timer-plugin xfce4-verve-plugin xfce4-weather-plugin xfce4-whiskermenu-plugin xfce4-wmdock-plugin xfce4-xkb-plugin xfconf-utils xfdesktop xfwm4
xfwm4-themes
0 будет обновлено, 0 новых установлено, 102 пакетов будет удалено и 3 не будет обновлено.
Необходимо получить 0B архивов.
После распаковки будет освобождено 122MB дискового пространства.
Продолжить? [Y/n] ^C
По крайней мере лишнего вроде не зацепило, и нашло если не все то многое.
Сам "костыль" (вернее его рабочий макет для проверки алгоритма):
from __future__ import print_function
import subprocess
import sys
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
def getDependency(package) :
if package == "":
return None
# resp = subprocess.check_output(["/bin/sh", "-c", "apt-cache depends "+ package +" | grep -v '<' | grep -v Требует | sort | uniq | sed 's/-[^-]*-[^-]*$//'"],universal_newlines=True);
resp = subprocess.check_output(["rpm" ,"--requires" , "--qf" ,"'%{REQUIRENAME}'", "-q" , package ],universal_newlines=True);
s = str(resp);
if s and len(s.strip()) > 0:
return s.replace("'","").split(sep="\n")
else:
return None
def getAllpackages() :
resp = subprocess.check_output(["rpm", "-qa" , "--qf", "'%{name}\n'"],universal_newlines=True);
s = str(resp)
return s.replace("'","").split(sep="\n")
def getWhatReq(package) :
# args = ["/bin/sh", "-c", "apt-cache whatdepends " + package + " | grep -v '<' | grep -v Требует | sort | uniq | sed 's/-[^-]*-[^-]*$//'"]
# resp = subprocess.check_output(["rpm", "--whatrequires", "--qf", "'%{name}\n'", "-q", package ],universal_newlines=True, stderr=None)
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);
if s and len(s.strip()) > 0:
return s.replace("'","").split(sep="\n")
else:
return None
candidats = {}
all = getAllpackages()
blacklist = set() # set(["dbus","control","grep","sed","samba_common","samba-client","udev","shadow-utils","tcb-utils","pam0-tcb","nss_tcb"])
def process_pckg_list(pckg_list) :
for package in pckg_list :
try:
dep = candidats[package]
hasBefore = True
except KeyError:
dep = set()
candidats[package] = dep
hasBefore = False
try :
list = getDependency(package)
if list == None:
return True
except subprocess.CalledProcessError :
eprint("erron while processing :", package)
# xtree.pop(package)
return False
for s in list :
s = s.strip()
if len(s) ==0 :
continue
if "(" in s :
continue
if "/" in s :
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 hasBefore :
eprint("blacklist:", pname );
blacklist.add(pname)
del candidats[pname]
except KeyError :
pass
return True
def main():
args = sys.argv #[-1]
args.pop(0)
args1 = args.copy()
for p in args :
list = getWhatReq(p)
if list:
list.remove('')
args1.extend(list)
args1 = set(args1)
eprint(args1)
process_pckg_list(args1)
# main(["Ristetto"])
# print(len(candidats))
# print(candidats)
# print("------------------")
needNextPass = False
passCount = 1
class NeedPassException(Exception):
pass
dep_cache = {}
#eprint(candidats)
while (True):
# eprint ("------------pass ", passCount)
passCount += 1
needNextPass = False
try:
for p in candidats:
try:
list = dep_cache[p]
except KeyError:
try:
list = getWhatReq(p)
dep_cache[p] = list
except subprocess.CalledProcessError:
# eprint("p=",p)
dep_cache[p] = []
continue
if list == None :
# eprint("getWhatReq(",p ,") return None" )
continue
for r in list:
r = r.strip()
if len(r) == 0:
continue
if r == p:
# eprint("skip [" + r + "]")
continue
if r not in all :
continue
if r not in candidats:
needNextPass = True
xlist = candidats[p]
for c1 in xlist:
try:
del candidats[c1]
# eprint("removed ",c1)
except KeyError:
pass
try :
del candidats[p]
# eprint("removed ", p)
except KeyError:
pass
raise NeedPassException
pass
pass
except NeedPassException:
continue
if not needNextPass:
break
pass
result = ''
eprint("Всего найдено пакетов для удаления:", len(candidats.keys()))
for s in candidats.keys():
result = result + s + " ";
print(result)
if __name__ == "__main__":
main()
Он сам ничего не удаляет, просто возвращает список пакетов, пригодный для "скармливанию" apt-get remove