diff options
author | Simon Sapin <simon.sapin@exyr.org> | 2020-04-21 10:46:36 +0200 |
---|---|---|
committer | Simon Sapin <simon.sapin@exyr.org> | 2020-04-21 10:54:21 +0200 |
commit | d2041e5b47d5eb239d55b71ef93c3ec3d468e508 (patch) | |
tree | da44186903954e23af61d7e3a30dbda6aa2fa1b4 /etc | |
parent | 4c8413d532ecd4bcd96e1a0b9649cfa9707677c4 (diff) | |
download | servo-d2041e5b47d5eb239d55b71ef93c3ec3d468e508.tar.gz servo-d2041e5b47d5eb239d55b71ef93c3ec3d468e508.zip |
Add a minimal alternative to `cargo graph`
I tried `cargo graph` and some of its successors,
but didn’t manage to make them produce what I wanted
(or in some cases make them work at all.)
This Python script reimplements similar functionality
based on parsing the (JSON) output of `cargo metadata`.
Graphviz graphs can become hard to read very quickly as the number of nodes grows.
Servo’s dependency graph is very large, so pruning as much as possible is important.
This only shows `path` dependencies (that have their source in this repo),
and can take a parameter to only show recursive dependencies of a given crate.
See https://github.com/servo/servo/issues/19422#issuecomment-617038366 for an example.
I find that `xdot` is best for visualization since it is interactive.
This script is not used by anything.
I am making this PR only so that we have it somewhere
in case it becomes useful again at some point.
Diffstat (limited to 'etc')
-rwxr-xr-x | etc/crates-graph.py | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/etc/crates-graph.py b/etc/crates-graph.py new file mode 100755 index 00000000000..7970c94119e --- /dev/null +++ b/etc/crates-graph.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +# Copyright 2013 The Servo Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution. +# +# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +import json +import os +import subprocess +import sys + + +def main(crate=None): + os.chdir(os.path.join(os.path.dirname(__file__), "..")) + meta = json.loads(subprocess.check_output(["cargo", "metadata", "--format-version", "1"])) + graph = {} + for package in meta["packages"]: + if package["source"] is None: # Lives in this repo + for dependency in package["dependencies"]: + if dependency["source"] is None: # Also lives in this repo + graph.setdefault(package["name"], []).append(dependency["name"]) + + if crate: + filtered = {} + seen = set() + + def traverse(name): + if name not in seen: + seen.add(name) + for dependency in graph.get(name, []): + filtered.setdefault(name, []).append(dependency) + traverse(dependency) + traverse(crate) + else: + filtered = graph + print("// This is in Graphviz DOT format.") + print("// Use the 'dot' or 'xdot' tool to visualize.") + print('digraph "local crates" {') + for package, dependencies in filtered.items(): + for dependency in dependencies: + print(' "%s" -> "%s";' % (package, dependency)) + print("}") + + +if __name__ == "__main__": + sys.exit(main(*sys.argv[1:])) |