summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/scripts/show_dependencies.py
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/botan/src/scripts/show_dependencies.py')
-rwxr-xr-xcomm/third_party/botan/src/scripts/show_dependencies.py213
1 files changed, 213 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/scripts/show_dependencies.py b/comm/third_party/botan/src/scripts/show_dependencies.py
new file mode 100755
index 0000000000..edf2d91e01
--- /dev/null
+++ b/comm/third_party/botan/src/scripts/show_dependencies.py
@@ -0,0 +1,213 @@
+#!/usr/bin/env python
+
+"""
+Show Botan module dependencies as a list or graph.
+
+Requires graphviz from pip when graphical output is selected:
+https://pypi.python.org/pypi/graphviz
+
+(C) 2015,2018 Simon Warta (Kullo GmbH)
+
+Botan is released under the Simplified BSD License (see license.txt)
+"""
+
+# global
+import argparse
+import copy
+import sys
+import subprocess
+from collections import OrderedDict
+import glob
+import os
+
+# Assume this script is in botan/src/scripts
+botan_root = os.path.join(os.path.dirname(sys.argv[0]), "..", "..")
+
+# locale
+sys.path.append(botan_root)
+from configure import ModuleInfo
+
+parser = argparse.ArgumentParser(description=
+ 'Show Botan module dependencies. '
+ 'The output is reduced by indirect dependencies, '
+ 'i.e. you must look at the result recursively to get all dependencies.')
+
+parser.add_argument('mode',
+ choices=["list", "draw"],
+ help='The output mode')
+parser.add_argument('--format',
+ nargs='?',
+ choices=["pdf", "png"],
+ default="pdf",
+ help='The file format (drawing mode only)')
+parser.add_argument('--engine',
+ nargs='?',
+ choices=["fdp", "dot"],
+ default="dot",
+ help='The graph engine (drawing mode only)')
+parser.add_argument('--all', dest='all', action='store_const',
+ const=True, default=False,
+ help='Show all dependencies. Default: direct dependencies only. (list mode only)')
+parser.add_argument('--verbose', dest='verbose', action='store_const',
+ const=True, default=False,
+ help='Verbose output (default: false)')
+args = parser.parse_args()
+
+files = []
+files += glob.glob(botan_root + '/src/lib/*/*/*/*/*/*/info.txt')
+files += glob.glob(botan_root + '/src/lib/*/*/*/*/*/info.txt')
+files += glob.glob(botan_root + '/src/lib/*/*/*/*/info.txt')
+files += glob.glob(botan_root + '/src/lib/*/*/*/info.txt')
+files += glob.glob(botan_root + '/src/lib/*/*/info.txt')
+files += glob.glob(botan_root + '/src/lib/*/info.txt')
+files += glob.glob(botan_root + '/src/lib/info.txt')
+files.sort()
+
+if len(files) == 0:
+ print("No info.txt files found.")
+ sys.exit(1)
+
+modules = []
+
+def dicts(t): return {k: dicts(t[k]) for k in t}
+
+def paths(t, path = [], level=0):
+ ret = []
+ for key in t:
+ ret.append(path + [key])
+ ret += paths(t[key], path + [key], level+1)
+ return ret
+
+if args.verbose:
+ print("Getting dependencies from into.txt files ...")
+
+for filename in files:
+ (rest, info_txt) = os.path.split(filename)
+ (rest, modname) = os.path.split(rest)
+ module = ModuleInfo(filename)
+ modules.append(module)
+ if args.verbose:
+ print(module.basename)
+ print("\t" + str(set(module.dependencies(None))))
+
+if args.verbose:
+ print(str(len(modules)) + " modules:")
+ names=[m.basename for m in modules]
+ names.sort()
+ print(names)
+ print("")
+
+if args.verbose:
+ print("resolving dependencies ...")
+
+def cartinality(depdict):
+ return sum([len(depdict[k]) for k in depdict])
+
+registered_dependencies = dict()
+all_dependencies = dict()
+direct_dependencies = dict()
+
+for module in modules:
+ lst = module.dependencies(None)
+ registered_dependencies[module.basename] = set(lst) - set([module.basename])
+
+# Get all_dependencies from registered_dependencies
+def add_dependency():
+ for key in all_dependencies:
+ potentially_new_modules_for_key = None
+ new_modules_for_key = None
+ for currently_in in all_dependencies[key]:
+ if currently_in in all_dependencies:
+ potentially_new_modules_for_key = all_dependencies[currently_in] - set([key])
+ if not potentially_new_modules_for_key <= all_dependencies[key]:
+ new_modules_for_key = potentially_new_modules_for_key.copy()
+ break
+ if new_modules_for_key:
+ all_dependencies[key] |= new_modules_for_key
+ return
+
+
+all_dependencies = copy.deepcopy(registered_dependencies)
+direct_dependencies = copy.deepcopy(registered_dependencies)
+
+# Sort
+all_dependencies = OrderedDict(sorted(all_dependencies.items()))
+direct_dependencies = OrderedDict(sorted(direct_dependencies.items()))
+
+#print(direct_dependencies)
+
+last_card = -1
+while True:
+ card = cartinality(all_dependencies)
+ # print(card)
+ if card == last_card:
+ break
+ last_card = card
+ add_dependency()
+
+# Return true iff a depends on b,
+# i.e. b is in the dependencies of a
+def depends_on(a, b):
+ if not a in direct_dependencies:
+ return False
+ else:
+ return b in direct_dependencies[a]
+
+def remove_indirect_dependencies():
+ for mod in direct_dependencies:
+ for one in direct_dependencies[mod]:
+ others = direct_dependencies[mod] - set([one])
+ for other in others:
+ if depends_on(other, one):
+ direct_dependencies[mod].remove(one)
+ return
+ # Go to next mod
+
+last_card = -1
+while True:
+ card = cartinality(direct_dependencies)
+ # print(card)
+ if card == last_card:
+ break
+ last_card = card
+ remove_indirect_dependencies()
+
+def openfile(f):
+ # pylint: disable=no-member
+ # os.startfile is available on Windows only
+ if sys.platform.startswith('linux'):
+ subprocess.call(["xdg-open", f])
+ else:
+ os.startfile(f)
+
+if args.verbose:
+ print("Done resolving dependencies.")
+
+if args.mode == "list":
+ if args.all:
+ for key in all_dependencies:
+ print(key.ljust(17) + " : " + ", ".join(sorted(all_dependencies[key])))
+ else:
+ for key in direct_dependencies:
+ print(key.ljust(17) + " : " + ", ".join(sorted(direct_dependencies[key])))
+
+if args.mode == "draw":
+ import graphviz as gv
+ import tempfile
+
+ tmpdir = tempfile.mkdtemp(prefix="botan-")
+
+ g2 = gv.Digraph(format=args.format, engine=args.engine)
+ g2.attr('graph', rankdir='RL') # draw horizontally
+ for key in direct_dependencies:
+ g2.node(key)
+ for dep in direct_dependencies[key]:
+ g2.edge(key, dep)
+
+ if args.verbose:
+ print("Rendering graph ...")
+ filename = g2.render(filename='graph', directory=tmpdir)
+
+ if args.verbose:
+ print("Opening " + filename + " ...")
+ openfile(filename)