aboutsummaryrefslogtreecommitdiffstats
path: root/etc
diff options
context:
space:
mode:
authorSimon Sapin <simon.sapin@exyr.org>2020-04-21 10:46:36 +0200
committerSimon Sapin <simon.sapin@exyr.org>2020-04-21 10:54:21 +0200
commitd2041e5b47d5eb239d55b71ef93c3ec3d468e508 (patch)
treeda44186903954e23af61d7e3a30dbda6aa2fa1b4 /etc
parent4c8413d532ecd4bcd96e1a0b9649cfa9707677c4 (diff)
downloadservo-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-xetc/crates-graph.py51
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:]))