|
#!/usr/bin/python |
|
|
|
import argparse |
|
import atexit |
|
import logging |
|
import subprocess |
|
from copy import deepcopy |
|
|
|
|
|
def get_dependencies(): |
|
dependson = {} |
|
usedby = {} |
|
f = subprocess.Popen('go mod graph', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) |
|
(stdout, stderr) = f.communicate() |
|
if stderr: |
|
logging.fatal(stderr) |
|
for line in stdout.splitlines(): |
|
key, value = line.decode().split(' ') |
|
key = key.split('@')[0] |
|
value = value.split('@')[0] |
|
dependson.setdefault(key, set()).add(value) |
|
usedby.setdefault(value, set()).add(key) |
|
return usedby, dependson |
|
|
|
|
|
def get_all_parents(dep, visited, usedby): |
|
visited.add(dep) |
|
if dep not in usedby: |
|
return set() |
|
array = usedby[dep].copy() |
|
for item in array.copy(): |
|
if item not in visited: |
|
array |= get_all_parents(item, visited, usedby) |
|
return array |
|
|
|
|
|
def draw_diagraph(items, skip): |
|
f = subprocess.Popen('go mod graph', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) |
|
(stdout, stderr) = f.communicate() |
|
if stderr: |
|
logging.fatal(stderr) |
|
print("digraph G {") |
|
print("rankdir=LR;") |
|
for line in stdout.splitlines(): |
|
key, value = line.decode().split(' ') |
|
|
|
if skip: |
|
key = key.split('@')[0] |
|
value = value.split('@')[0] |
|
|
|
found_key = False |
|
found_value = False |
|
for item in items: |
|
if key.startswith(item): |
|
found_key = True |
|
if value.startswith(item): |
|
found_value = True |
|
if found_key and found_value: |
|
print("\"%s\" -> \"%s\"" % (key, value)) |
|
print("}") |
|
|
|
|
|
chains = {} |
|
|
|
|
|
def print_chains(): |
|
longest = max(chains.keys()) |
|
print("Longest chain is:", longest) |
|
print("%r" % chains[longest]) |
|
|
|
|
|
def visit_node(dep, parents, dependson): |
|
parents.append(dep) |
|
if dep in dependson: |
|
for item in dependson[dep]: |
|
if item not in parents: |
|
visit_node(item, deepcopy(parents), dependson) |
|
else: |
|
chains.setdefault(len(parents), list()).append(parents) |
|
else: |
|
chains.setdefault(len(parents), list()).append(parents) |
|
|
|
|
|
def main(): |
|
parser = argparse.ArgumentParser() |
|
parser.add_argument('-p', '--package', required=True) |
|
parser.add_argument('-s', '--skip', action='store_true') |
|
parser.add_argument('-d', '--depth', action='store_true') |
|
args = parser.parse_args() |
|
|
|
usedby, dependson = get_dependencies() |
|
if args.depth: |
|
atexit.register(print_chains) |
|
visit_node(args.package, [], dependson) |
|
print_chains() |
|
else: |
|
parents = get_all_parents(args.package, set(), usedby) |
|
draw_diagraph(parents | {args.package}, args.skip) |
|
|
|
|
|
if __name__ == "__main__": |
|
main() |