mirror of
https://review.haiku-os.org/haiku
synced 2025-01-18 12:38:51 +01:00
Add a script to draw a dependency graph from a set of hpkg files
Useful for understanding dependency chains. Change-Id: I64113ff87fe3cef2f45796b064749e0c6a5bf880
This commit is contained in:
parent
488ab9b45f
commit
4c07199d82
82
3rdparty/pulkomandy/pkggraph.py
vendored
Executable file
82
3rdparty/pulkomandy/pkggraph.py
vendored
Executable file
@ -0,0 +1,82 @@
|
||||
#!python3
|
||||
#
|
||||
# Copyright 2019-2023 Adrien Destugues <pulkomandy@pulkomandy.tk>
|
||||
#
|
||||
# Distributed under terms of the MIT license.
|
||||
|
||||
from os import listdir
|
||||
from os.path import isfile, join
|
||||
import subprocess
|
||||
import re
|
||||
import sys
|
||||
|
||||
"""
|
||||
Generate a graph of dependencies for a set of packages packages in an Haiku system.
|
||||
|
||||
Usage:
|
||||
- Without arguments: generate a graph of all packages in /system/packages. This can be quite busy
|
||||
and hard to understand. It will also take a while to generate the graph, as dot tries to route
|
||||
thousands of edges.
|
||||
- With arguments: the arguments are a list of packages to analyze. This allows to print a subset
|
||||
of the packages for a better view.
|
||||
|
||||
Dependencies are resolved: if a package has a specific string in its REQUIRES and another has the
|
||||
same string in its PROVIDES, a BLUE edge is drawn between the two package.
|
||||
If a package has a REQUIRES that is not matched by any other package in the set, this REQUIRE entry
|
||||
is drawn as a node, and the edge pointing to it is RED (so you can easily see missing dependencies
|
||||
in a package subset). If you use the complete /system/packages hierarchy, there should be no red
|
||||
edges, all dependencies are satisfied.
|
||||
|
||||
The output of the script can be saved to a file for manual analysis (for example, you can search
|
||||
packages that nothing points to, and see if you want to uninstall them), or piped into dot for
|
||||
rendering as a PNG, for example:
|
||||
|
||||
cd /system/packages
|
||||
pkggraph.py qt* gst_plugins_ba* | dot -Tpng -o /tmp/packages.png
|
||||
ShowImage /tmp/packages.png
|
||||
"""
|
||||
|
||||
path = "/system/packages"
|
||||
if len(sys.argv) > 1:
|
||||
packages = sys.argv[1:]
|
||||
else:
|
||||
packages = [join(path, f) for f in listdir(path) if(isfile(join(path, f)))]
|
||||
|
||||
print('strict digraph {\nrankdir="LR"\nsplines=ortho\nnode [ fontname="Noto", fontsize=10];')
|
||||
|
||||
pmap = {}
|
||||
rmap = {}
|
||||
|
||||
for p in packages:
|
||||
pkgtool = subprocess.Popen(['package', 'list', '-i', p], stdout = subprocess.PIPE)
|
||||
infos, stderr = pkgtool.communicate()
|
||||
|
||||
provides = []
|
||||
requires = []
|
||||
|
||||
for line in infos.split(b'\n'):
|
||||
if line.startswith(b"\tprovides:"):
|
||||
provides.append(line.split(b' ')[1])
|
||||
if line.startswith(b"\trequires:"):
|
||||
line = line.split(b' ')[1]
|
||||
if b'>' in line:
|
||||
line = line.split(b'>')[0]
|
||||
if b'=' in line:
|
||||
line = line.split(b'=')[0]
|
||||
if line != b'haiku' and line != b'haiku_x86':
|
||||
requires.append(line)
|
||||
|
||||
for pro in provides:
|
||||
pmap[pro] = provides[0]
|
||||
if len(requires) > 0:
|
||||
rmap[provides[0]] = requires
|
||||
|
||||
for k,v in rmap.items():
|
||||
for dep in v:
|
||||
color = "red"
|
||||
if dep in pmap:
|
||||
dep = pmap[dep]
|
||||
color = "blue"
|
||||
print('"%s" -> "%s" [color=%s]' % (k.decode('utf-8'), dep.decode('utf-8'), color))
|
||||
|
||||
print("}")
|
Loading…
Reference in New Issue
Block a user