Skip to content

Instantly share code, notes, and snippets.

@vyskocilm
Last active August 29, 2015 14:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vyskocilm/f5f64c1e94ea42326ec5 to your computer and use it in GitHub Desktop.
Save vyskocilm/f5f64c1e94ea42326ec5 to your computer and use it in GitHub Desktop.
import subprocess
import collections
import io
import sys
import os
import shlex
__doc__ = """
Tool for printing dependency tree for Debian systems including size of package. Might help with
stripping down dependencies.
Usage:
DPKG=ssh someone@somewhere dpkg python debsize.py > somewhere.dot
dot -Tsvg somewhere.dot > somewhere.svg
"""
DPKG=["dpkg", ]
dpkg_v = os.getenv("DPKG")
if dpkg_v:
DPKG=shlex.split(dpkg_v)
del dpkg_v
def kp(string):
ret = list()
kill=False
for ch in string:
if ch == '(':
kill=True
if not kill:
ret.append(ch)
if ch == ')' and kill:
kill=False
return "".join(ret).split('|')[0]
def parse_depends(depends):
return [kp(item).strip() for item in depends.split(',')]
DpkgRes = collections.namedtuple("DpkgRes", "package, depends, suggests, size")
def parse_dpkg_status(f):
package = ""
depends = []
suggests = []
size = 0
for line in f:
if line.startswith("Package:"):
package = line.split(':')[1].strip()
elif line.startswith("Installed-Size:"):
size = int(line.split(':')[1].strip())
elif line.startswith("Depends:"):
depends.extend(parse_depends(line.split(':')[1]))
elif line.startswith("Pre-Depends:"):
depends.extend(parse_depends(line.split(':')[1]))
elif line.startswith("Suggests:"):
suggests.extend(parse_depends(line.split(':')[1]))
elif line.startswith("Recommends:"):
suggests.extend(parse_depends(line.split(':')[1]))
return DpkgRes(package, depends, suggests, size)
def parse_dpkg_list(f):
ret = set()
for line in f:
if not line.startswith("ii"):
continue
name = line.split()[1]
if ':' in name:
name = name.split(':')[0]
ret.add(name)
return ret
def dpkg_status(name):
assert name
global DPKG
return io.BytesIO(subprocess.check_output(DPKG + ["-s", name,]))
def dpkg_list():
global DPKG
return io.BytesIO(subprocess.check_output(DPKG + ["-l", ]))
def self_test():
with open("dpkg.info", "r") as f:
print(parse_dpkg_status(f))
with open("dpkg.list", "r") as f:
print(parse_dpkg_list(f))
# main
print("digraph debian {");
packages = parse_dpkg_list(dpkg_list())
for package in packages:
status = parse_dpkg_status(dpkg_status(package))
print('"%(package)s" [label="%(package)s (%(size)d)"];' % dict(package=package, size=status.size))
for dep in status.depends:
print('"%(package)s" -> "%(dep)s";' % dict(package=package, dep=dep))
sys.stdout.flush()
for dep in (dep for dep in status.suggests if dep in packages):
print('"%(package)s" -> "%(dep)s" [style=dotted];' % dict(package=package, dep=dep))
sys.stdout.flush()
#TODO suggests
print("}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment